5

I have noticed that some smart contracts have addresses that start with 0x0000, 0x1234, or0x1337 - and I'm not sure how the deployers managed to do this. ​ Is it possible to do this on RSK?

Irene Patrikios
  • 249
  • 1
  • 5

1 Answers1

4

Building upon the previous answer, using the CREATE2 opcode - it is not only possible to predict the address that a smart contract will be deployed at, but also (partially) choose the address that you would like it to be deployed at.

For example, if you want a vanity address that starts with 4 leading zeroes, you use the following helper function, which checks for a match of the required vanity address:

  function hasLeadingZeros(address = '0x0000', zeros = 4) {
    for (let i = 2; i <= zeros + 1; i += 1) {
      if (address.charAt(i) !== '0') return false;
    }
    return true;
  }

The next helper function uses trial and error, since keccak256 as with other hashes are 1-way functions, to determine which salt parameter will result in obtaining a required vanity address.

  function getSaltForVanityAddress(deployerAddress, initCodeHash) {
    let salt = 0;
    let vanityAddress = '';
    let saltHash;
    while (!hasLeadingZeros(vanityAddress)) {
      salt += 1;
      saltHash = ethers.utils.keccak256(salt);
      vanityAddress = ethers.utils.getCreate2Address(
        deployerAddress,
        saltHash,
        initCodeHash,
      );
    }
    return saltHash;
  }

By combine the above, you can use factory.deployCreate2(salt); to deploy a smart contract with the address needed. Here is a test case to illustrate:

  it('Should deploy Child to the address starting with four zeros', async () => {
    const Child = await ethers.getContractFactory('Child');
    const { data: initCode } =
      Child.getDeployTransaction(deployer.address);
    const initCodeHash = ethers.utils.keccak256(initCode);
    const salt = getSaltForVanityAddress(factory.address, initCodeHash);
    const deployTx = await factory.deployCreate2(salt);
    const txReceipt = await deployTx.wait();
    const deployEvent = txReceipt.events.find(
      (event) => event.event === 'ContractDeployed',
    );
    expect(hasLeadingZeros(
      deployEvent.args.childContract)
    ).to.be.true;
    console.log(
      `Found salt '${salt}' such that the\ndeployed s/c address is ${deployEvent.args.childContract}`,
    );
  });

Found salt '0xb20ba450430132a5f0191bd27fc7e8018b39435484af81bbdf289296ae61ea75' such that the
deployed s/c address is 0x0000b36619Df7e2816577549b78CBB8b189e8d6B
    ✔ Should deploy Child to the address starting with four zeros (4973ms)
Aleks Shenshin
  • 2,117
  • 5
  • 18