Deploy contract error using ITX

Hi everyone,

We’re using ITX with ether.js to deploy a contract but we get the following error: “insufficient funds for intrinsic transaction cost”.
We do get the gas tank balance without errors, but we can’t deploy the contract using relay_sendTransaction method.
We’ve followed ITX docs, and configured the provider, the signer and the signRequest methods.

Our code is:
const factory = new ethers.ContractFactory(abi, bytecode, signer);
const gasPrice = await itx.estimateGas(factory.signer.address);

const tx = {
  to: '0x0000000000000000000000000000000000000000',
  data: '0x' + bytecode,
  gas: '200000',
  schedule: 'slow'
}

const signature = await signRequest(tx)

const relayTransactionHash = await itx.send('relay_sendTransaction', [
  tx,
  signature
]);

const contract = await factory.deploy({
  gasPrice: gasPrice,
  gasLimit: 200000
  });

console.log(contract.address);
console.log(contract.deployTransaction);
console.log(`ITX relay hash: ${relayTransactionHash}`)

When we run the code twice, console message is “Transaction already sent.”

Can anyone tell us what we’re doing wrong or if this is a bug? I can add console logs if needed.

Thanks in advance,
Andy

Hi Andy,

Based on the code snippet, there are a few things to check.

const gasPrice = await itx.estimateGas(factory.signer.address);

I assume ‘itx’ is the InfuraProvider. This looks to be a mistake as eth_estimateGas returns the gas limitused for the transaction and not the gas price. It will impact the following code:

const contract = await factory.deploy({
  gasPrice: gasPrice,
  gasLimit: 200000
  });

It also seems that this piece of code is trying to deploy the smart contract to Ethereum using your own ETH/signing key. I suspect the error message insufficient funds for intrinsic transaction cost is being triggered by this line of code as your signer has no funds. If you are deploying the contract via ITX (as it seems to be) then you can just delete the above code altogether.

You are already deploying the contract with the itx.send(...). You can use the relay transaction hash to fetch the Ethereum transaction that is eventually mined via relay_getTransactionStatus(relayTxHash).

When it is mined, you can use eth_getTransactionReceipt(ethTxHash) to fetch the receipt and it has a contractAddress.

When we run the code twice, console message is “Transaction already sent.”

Yeah. ITX will not accept the exact same transaction within a short period of time. It is mostly to prevent bugs where the user may send us multiple transactions by mistake. It seems to cause more confusion than it solves though. A quick way to get around it is to just change the gas limit of the relay transaction (i.e., change 200000 to 200001).

I hope the above helps. If there is any trouble or some information I am missing, do let us know and I’ll get back as soon as possible.

1 Like

Thank you Patrick! I’ve changed my code following your indications and it works like a charm!

This is not related with my previous question, but there’s a broken link in the ITX documentation. On the " Check if relay request is mined" section, the link to the demo repository is broken.

Thanks again Patrick!

The correct link should be:

I’ll notify web team to fix the link. Thanks for pointing it out and hopefully all goes well :slight_smile:

Hi Patrick,
I’ve another problem right now. I can deploy my contract using ether.js getContractAddress method to calculate an address before deploying the contract. But his “future” address is not working right.

I also tried with “0x0000000000000000000000000000000000000000” as the deployment address value. But with this value the contract doesn’t deploy.

My main problem is that the contractAddress from the eth_getTransactionReceipt(ethTxHash) receipt is either null (when using a “to” value calculated with getContractAddress) either wrong.

So, how can I get the correct contractAddress?

My code is similar to this:

const futureContractAddress = ethers.utils.getContractAddress(transaction);

const tx = {
  to: '0x0000000000000000000000000000000000000000',
  data: '0x' + bytecode,
  gas: '120869',
  schedule: 'fast
}
const signature = await signRequest(tx);

// Send signed transaction
const relayTransactionHash = await itx.send('relay_sendTransaction', [tx, signature]);

const receipt = await waitTransaction(relayTransactionHash);
if (receipt.status === false || receipt.status === 0) {
  throw new Error('Error while deploying contract.');
}

Thanks!

Hi Andres,

The contract address is computed as roughly:

contractAddress = h(tx_signer, nonce).

The getContractAddress function will not work as ITX will be the transaction signer.

I recommend double-checking what bytecode will be in:

const tx = {
  to: '0x0000000000000000000000000000000000000000',
  data: '0x' + bytecode,
  gas: '120869',
  schedule: 'fast
}

Ethers should already append “0x” onto bytecode, so you might end up with “0x0x” which is not valid. That may explain the receipt returning null. The “0x000…” is correct, although Ethers has a global constant AddressZero you can use.

The receipt has a field contract address, so you can fetch it using:

  console.log("Contract address: " + receipt.contractAddress!);

I have put together a simple script (it won’t run since its missing some imports, but it provides a good idea on how to do it):

Thanks a lot Patrick!

The '0x' + bytecode line wasn’t a problem, but global constant AddressZero and looking at your code were definitely helpful.

In fact, my problem wasn’t really in the code I’ve put here, but thanks to your tips I was able to solve it.

So thanks again Patrick!

1 Like