Ethereum Smart Contract Address Calculation: CREATE vs CREATE2

ยท

Introduction to Ethereum Contract Creation

Ethereum offers two primary methods for deploying smart contracts:

  1. Direct creation by Externally Owned Accounts (EOAs)
  2. Creation via other smart contracts:

    • Using CREATE opcode (0xf0)
    • Using CREATE2 opcode (0xf5)

The choice between these methods impacts address predictability, upgradeability, and cross-chain security considerations.

EOA-Created Contracts: Address Calculation

When an EOA creates a contract, the address is deterministically calculated using:

address = keccak256(rlp_encode(sender_address, nonce))[12:]

Key characteristics:

Solidity Implementation Examples

Basic Implementation (Solidity 0.8+):

function addressFrom(address _origin, uint _nonce) public pure returns (address) {
    bytes memory data;
    if (_nonce == 0x00) data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x80));
    else if (_nonce <= 0x7f) data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, uint8(_nonce));
    // Additional cases for larger nonce values...
    return address(uint160(uint256(keccak256(data))));
}

Gas-Optimized Assembly Version:

function addressFrom(address _origin, uint _nonce) external pure returns (address _address) {
    bytes memory data;
    if(_nonce == 0x00) data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x80));
    else if(_nonce <= 0x7f) data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, uint8(_nonce));
    // Additional cases...
    assembly {
        mstore(0, keccak256(data, add(data, 0x20), mload(data)))
        _address := mload(0)
    }
}

Contract-Created Contracts: CREATE vs CREATE2

CREATE (0xf0) Operation

CREATE2 (0xf5) Operation

Introduced in EIP-1014 with the formula:

address = keccak256(0xff ++ sender ++ salt ++ keccak256(init_code))[12:]

Key advantages:

๐Ÿ‘‰ Learn more about advanced contract deployment strategies

Security Considerations

  1. Cross-chain protection: Derive new salts using:

    bytes20 newSalt = bytes20(keccak256(abi.encodePacked(_initializerData, _salt)));
  2. Address collisions: The 0xff prefix prevents CREATE/CREATE2 collisions
  3. Upgrade patterns: CREATE2 enables interesting upgrade architectures

Practical Examples

CREATE2 Deployment Code Example

function deployWithCREATE2(
    bytes memory bytecode,
    bytes32 salt
) public returns (address) {
    address addr;
    assembly {
        addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
        if iszero(extcodesize(addr)) {
            revert(0, 0)
        }
    }
    return addr;
}

FAQ Section

Q: Why would I use CREATE2 instead of CREATE?

A: CREATE2 provides address predictability, enables advanced upgrade patterns, and offers better cross-chain deployment safety when proper salt derivation is used.

Q: How does the 0xff prefix prevent address collisions?

A: The 0xff byte makes RLP-encoded CREATE addresses impossibly large (petabyte-scale) if they were to collide with CREATE2 addresses, effectively preventing practical collisions.

Q: Can I redeploy different code to the same CREATE2 address?

A: Yes, through metamorphic contract patterns, but only if you control the original deployment and use the same salt/bytecode hash combination.

๐Ÿ‘‰ Explore real-world CREATE2 applications

Conclusion

Understanding Ethereum contract address calculation is crucial for:

The choice between CREATE and CREATE2 depends on your specific requirements for address predictability, upgradeability, and security considerations.