pub fn derive_create3_address(
factory: Address,
deployer: Address,
salt: B256,
) -> AddressExpand 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:
mixedSalt = keccak256(abi.encodePacked(deployer, salt))— binds the salt to the logical deployer.proxy = create2(factory, mixedSalt, CREATE3_PROXY_INITCODE_HASH)— the CREATE2 address of the proxy.CREATE3_PROXY_INITCODE_HASHis the keccak256 of the fixed proxy init code, so the proxy address is fully determined by the factory and mixed salt.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]:0xd6is the RLP list header for the 22-byte payload that follows,0x94introduces the 20-byteproxyaddress, and0x01is the RLP encoding of the proxy’s nonce (1), since a fresh contract account’s firstCREATEuses 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));