[Ethereum] How to calculate an Ethereum Contract’s address during its creation using the Solidity language

contract-developmentcryptographyethersolidity

Now I know and have read the other thread saying that a contract's address is created deterministically via RLP encoding the creator's address and his nonce and then hashed with Keccak-256 but the problem is the solution is provided in Python.

I am currently coding in Solidity and although I have tried porting the solution over to Solidity, Solidity does not support multi-type arrays to my knowledge which is required by the rlp_encoder function. Any help or tips on how to achieve this in Solidity would be appreciated! (The nonce would be given as input during the contract creation)

Best Answer

The most optimized version:

function addressFrom(address _origin, uint _nonce) public pure returns (address) {
    bytes memory data;
    if (_nonce == 0x00)          data = abi.encodePacked(byte(0xd6), byte(0x94), _origin, byte(0x80));
    else if (_nonce <= 0x7f)     data = abi.encodePacked(byte(0xd6), byte(0x94), _origin, byte(_nonce));
    else if (_nonce <= 0xff)     data = abi.encodePacked(byte(0xd7), byte(0x94), _origin, byte(0x81), uint8(_nonce));
    else if (_nonce <= 0xffff)   data = abi.encodePacked(byte(0xd8), byte(0x94), _origin, byte(0x82), uint16(_nonce));
    else if (_nonce <= 0xffffff) data = abi.encodePacked(byte(0xd9), byte(0x94), _origin, byte(0x83), uint24(_nonce));
    else                         data = abi.encodePacked(byte(0xda), byte(0x94), _origin, byte(0x84), uint32(_nonce));
    return address(keccak256(data));
}

Update for Solidity 0.6.x:

function addressFrom(address _origin, uint _nonce) public pure returns (address) {
    bytes memory data;
    if (_nonce == 0x00)          data = abi.encodePacked(byte(0xd6), byte(0x94), _origin, byte(0x80));
    else if (_nonce <= 0x7f)     data = abi.encodePacked(byte(0xd6), byte(0x94), _origin, uint8(_nonce));
    else if (_nonce <= 0xff)     data = abi.encodePacked(byte(0xd7), byte(0x94), _origin, byte(0x81), uint8(_nonce));
    else if (_nonce <= 0xffff)   data = abi.encodePacked(byte(0xd8), byte(0x94), _origin, byte(0x82), uint16(_nonce));
    else if (_nonce <= 0xffffff) data = abi.encodePacked(byte(0xd9), byte(0x94), _origin, byte(0x83), uint24(_nonce));
    else                         data = abi.encodePacked(byte(0xda), byte(0x94), _origin, byte(0x84), uint32(_nonce));
    return address(uint256(keccak256(data)));
}
Related Topic