Skip to main content

derive_create3_address

Function derive_create3_address 

Source
pub fn derive_create3_address(
    factory: Address,
    deployer: Address,
    salt: B256,
) -> Address
Expand description

Derive CREATE3 deployment address for the universal factory implementation.

CREATE3 deploys in two hops: the factory first CREATE2-deploys a tiny fixed proxy, then that proxy CREATEs the actual contract as its first (nonce-1) deployment. Because both hops use only the factory, the salt, and a fixed proxy init code, the final address depends solely on factory, deployer, and salt — it is independent of the deployed contract’s bytecode. Two different contracts deployed with the same inputs land at the same address.

Formula:

  1. mixedSalt = keccak256(abi.encodePacked(deployer, salt)) — binds the salt to the logical deployer.
  2. proxy = create2(factory, mixedSalt, CREATE3_PROXY_INITCODE_HASH) — the CREATE2 address of the proxy. CREATE3_PROXY_INITCODE_HASH is the keccak256 of the fixed proxy init code, so the proxy address is fully determined by the factory and mixed salt.
  3. deployed = address(keccak256(rlp([proxy, 1]))) — the CREATE address of the proxy’s first deployment (nonce 1). The RLP framing bytes encode the short list [proxy, 1]: 0xd6 is the RLP list header for the 22-byte payload that follows, 0x94 introduces the 20-byte proxy address, and 0x01 is the RLP encoding of the proxy’s nonce (1), since a fresh contract account’s first CREATE uses nonce 1.

The address is returned as the low 20 bytes of each keccak256 hash, matching the EVM’s address-from-hash convention.

factory lets you derive against a non-canonical factory deployment; for the canonical address use derive_universal_create3_address.

use evm_fork_cache::create3::derive_create3_address;
use alloy_primitives::{Address, B256, address, b256};

let factory: Address = address!("93FEC2C00BfE902F733B57c5a6CeeD7CD1384AE1");
let deployer: Address = address!("00000000000000000000000000000000000000aa");
let salt: B256 =
    b256!("1111111111111111111111111111111111111111111111111111111111111111");

// The derivation is a pure function of (factory, deployer, salt): identical
// inputs always yield the same address.
let a = derive_create3_address(factory, deployer, salt);
let b = derive_create3_address(factory, deployer, salt);
assert_eq!(a, b);

// Changing the salt changes the derived address.
let other_salt: B256 =
    b256!("2222222222222222222222222222222222222222222222222222222222222222");
assert_ne!(a, derive_create3_address(factory, deployer, other_salt));