deriveContractAddress static method
Derives the smart-account contract address from a credential ID and deployer.
Computes the deterministic contract address that will be created when deploying a smart-account contract with the given credential ID from the specified deployer account on the specified network. The algorithm is:
salt = SHA-256(credentialId)
deployerAddress = SCAddress::Account(deployerPublicKey)
networkId = SHA-256(networkPassphrase as UTF-8)
preimage = HashIDPreimage::ContractID {
networkId,
contractIDPreimage: ContractIDPreimage::FromAddress {
address: deployerAddress,
salt: Uint256(salt),
}
}
contractIdBytes = SHA-256(XDR_encode(preimage))
contractId = StrKey.encodeContractId(contractIdBytes)
Throws SmartAccountInvalidAddress when deployerPublicKey is invalid,
SmartAccountInvalidInput when contract-ID encoding fails, and
SmartAccountTransactionSigningFailed when XDR encoding fails.
Implementation
static String deriveContractAddress({
required Uint8List credentialId,
required String deployerPublicKey,
required String networkPassphrase,
}) {
final contractSalt = getContractSalt(credentialId);
XdrSCAddress deployerAddress;
try {
// KeyPair.fromAccountId validates the strkey form for us; reuse
// it so smart-account derivation matches the rest of the SDK.
KeyPair.fromAccountId(deployerPublicKey);
deployerAddress = XdrSCAddress.forAccountId(deployerPublicKey);
} catch (e) {
throw SmartAccountValidationException.invalidAddress(
deployerPublicKey,
cause: e,
);
}
final networkIdBytes = Uint8List.fromList(
crypto.sha256.convert(utf8.encode(networkPassphrase)).bytes,
);
final fromAddress = XdrContractIDPreimageFromAddress(
deployerAddress,
XdrUint256(contractSalt),
);
final contractIdPreimage = XdrContractIDPreimage(
XdrContractIDPreimageType.CONTRACT_ID_PREIMAGE_FROM_ADDRESS,
);
contractIdPreimage.fromAddress = fromAddress;
final hashIdPreimageContractId = XdrHashIDPreimageContractID(
XdrHash(networkIdBytes),
contractIdPreimage,
);
final preimage = XdrHashIDPreimage(
XdrEnvelopeType.ENVELOPE_TYPE_CONTRACT_ID,
);
preimage.contractID = hashIdPreimageContractId;
Uint8List encodedPreimage;
try {
final stream = XdrDataOutputStream();
XdrHashIDPreimage.encode(stream, preimage);
encodedPreimage = Uint8List.fromList(stream.bytes);
} catch (e) {
throw SmartAccountTransactionException.signingFailed(
'Failed to XDR encode contract ID preimage',
cause: e,
);
}
final contractIdBytes = Uint8List.fromList(
crypto.sha256.convert(encodedPreimage).bytes,
);
try {
return StrKey.encodeContractId(contractIdBytes);
} catch (e) {
throw SmartAccountValidationException.invalidInput(
'contractId',
'Failed to encode contract ID: $e',
cause: e,
);
}
}