Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find out in advance the address of the smart contract I am going to deploy?

Tags:

solidity

rsk

I have a Solidity smart contract ContractFactory which I am deploying on RSK and developing in Hardhat. ContractFactory has a deploy function which produces new Child smart contracts. ​

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
​
contract ContractFactory {
    event ContractDeployed(address owner, address childContract);
​
    function deploy() public {
        Child newContract = new Child(msg.sender);
        emit ContractDeployed(msg.sender, address(newContract));
    }
}
​
contract Child {
    address owner;
​
    constructor(address _owner) {
        owner = _owner;
    }
}

Can I know before invoking the deploy function what address on RSK will a new Child smart contract receive?

like image 878
Owans Avatar asked Jan 24 '26 00:01

Owans


2 Answers

You can go even further and make use of the deterministic deployment technique which exploits CREATE2 specification. Here the address of the future smart contract is a keccak256 hash of the 4 parameters:

  1. 0xFF, a constant that prevents collisions with CREATE
  2. the sender’s own address
  3. salt (an arbitrary 32 bytes long value provided by the sender)
  4. keccak256 of the to-be-deployed contract’s bytecode

Notice that with CREATE2 you can not only predict the deployed smart contract address, but you can actually influence what this address will be by changing the salt value.

Try adding the following function to your ContractFactory

function deployCreate2(bytes32 _salt) public {
    Child newContract = new Child{salt: _salt}(msg.sender);
    emit ContractDeployed(msg.sender, address(newContract));
}

With this test you can determine the deployed smart contract address.

it('Should determine the Child address', async () => {
    const Child = await ethers.getContractFactory('Child');
    const { data: initCode } = Child.getDeployTransaction(deployer.address);
    const initCodeHash = ethers.utils.keccak256(initCode);
    const salt = ethers.utils.keccak256(0x0);
    const childAddress = ethers.utils.getCreate2Address(
      factory.address,
      salt,
      initCodeHash,
    );
    const deployTx = factory.deployCreate2(salt);
    await expect(deployTx)
      .to.emit(factory, 'ContractDeployed')
      .withArgs(deployer.address, childAddress);
});
like image 147
Aleks Shenshin Avatar answered Jan 26 '26 05:01

Aleks Shenshin


Yes you can. The deployed smart contract address is a function (keccak256 hash) of 2 parameters:

  1. the deployer address (EAO or another smart contract)
  2. the nonce which is a transaction count for the deployer address You can use Ethers.js getTransactionCount function to find the nonce, and getContractAddress function to calculate the future smart contract address.

Use this test to predict the Child address:

it('Should predict Child address', async () => {
    const nonce = await ethers.provider.getTransactionCount(factory.address);
    const anticipatedAddress = ethers.utils.getContractAddress({
      from: factory.address,
      nonce,
    });
    const tx = await factory.deploy();
    await expect(tx)
      .to.emit(factory, 'ContractDeployed')
      .withArgs(deployer.address, anticipatedAddress);
});
like image 26
Ahsan Avatar answered Jan 26 '26 05:01

Ahsan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!