What type of topic is this?
Support
Hello everyone,
I’m working on a larger project and need to get this piece working. Specifically, I’m retrieving the public key from the canister, deriving the corresponding Ethereum address, and funding that address so I can convert its balance into ckEth via the handler contract. However, whenever I broadcast the ETH transaction, I keep getting an “insufficient balance” error.
Here are the canisters methods
Github: andredevjs/poc-cketh/blob/main/src/eth-bridge-poc-backend/utils/ECDSA.mo
public func getPublicKey(caller: Principal) : async { #Ok : { public_key_hex: Text }; #Err : Text } {
try {
let { public_key } = await ic.ecdsa_public_key({
canister_id = null;
derivation_path = [ Principal.toBlob(caller) ];
key_id = { curve = #secp256k1; name = "dfx_test_key" };
});
#Ok({ public_key_hex = Hex.encode(Blob.toArray(public_key)) })
} catch (err) {
#Err(Error.message(err))
}
};
public func sign(caller: Principal, message: Text) : async { #Ok : { signature_hex: Text }; #Err : Text } {
try {
let message_hash: Blob = Blob.fromArray(SHA256.sha256(Blob.toArray(Text.encodeUtf8(message))));
Cycles.add<system>(30_000_000_000);
let { signature } = await ic.sign_with_ecdsa({
message_hash;
derivation_path = [ Principal.toBlob(caller) ];
key_id = { curve = #secp256k1; name = "dfx_test_key" };
});
#Ok({ signature_hex = Hex.encode(Blob.toArray(signature))})
} catch (err) {
#Err(Error.message(err))
}
};```
And the JS here
andredevjs/poc-cketh/blob/main/src/eth-bridge-poc-frontend/src/App.jsx
const principal = principalToBytes32(OwnerPrincipal);
const subaccount = principalToBytes32(DevJourneyPrincipal);
const amount = ethers.parseEther("0.01");
console.log("🔑 Derived address:", signerAddress);
// 2) Fetch balance, fee data, and network in parallel
const [balance, feeData, network] = await Promise.all([
provider.getBalance(signerAddress),
provider.getFeeData(),
provider.getNetwork()
]);
console.log("🌐 Network:", network.name, "(chainId:", network.chainId + ")");
console.log("💰 Balance:", ethers.formatEther(balance), "ETH");
const tx = await contract.depositEth.populateTransaction(
principal,
subaccount,
{
value: amount,
gasLimit: 23600,
gasPrice: feeData.gasPrice,
},
);
const unsignedSerialized = serialize(tx);
const unsignedBytes = ethers.getBytes(unsignedSerialized);
const digest = keccak256(unsignedBytes);
const result = await eth_bridge_poc_backend.sign(digest);
const signatureHex ='0x' + result.Ok.signature_hex;
const signature = ethers.Signature.from(signatureHex);
const txHex = serialize({...tx}, signature);
console.log(ethers.Transaction.from(txHex).from);
const txResponse = await provider.broadcastTransaction(txHex);
console.log('Transaction Hash:', txResponse);
// Wait for the transaction to be mined
const receipt = await txResponse.wait();
console.log('Transaction mined in block:', receipt.blockNumber);
But I always get this error:
ethers.js?v=a7670b8a:325 Uncaught (in promise) Error: insufficient funds for intrinsic transaction cost (transaction="0xf8b0808501ee0a87c2825c30942d39863d30716aaf2b7fffd85dd03dda2bfc2e38872386f26fc10000b84417c819c41dde12780352f89e9505135cd6167b5ee8776ad3c8fb1bd384c8b00a150200001da527d220b995574d0f5e8f31ea96fda034f292dc652d9d4a94a4bd130200001ba0e6df99a65bc47303170f9e40fec1bec34f6f31decd092edca65aca86a4f73f57a03731a0989e9cb38a0e0cd0c3d0b0d2e587093
The generated address is fine, because I double check that I get the same value in both JS and Rust, so it's gotta be something with the signature.
Any ideas what could I be doing wrong?