Early rate$2,400 of senior audit time for $500. Early members keep the rate as it climbs.$2,400 of senior audit time for $500See how

CREATE2

An EVM opcode that deploys a contract to an address derived deterministically from the deployer, a salt, and the init code hash, making the address computable before deployment.

CREATE2 deploys a contract to an address that is a pure function of four inputs: the constant 0xff, the deployer's address, a 32-byte salt, and the keccak256 hash of the creation bytecode. The result is hashed and truncated to 20 bytes.

Unlike CREATE, which folds in the deployer's nonce and therefore depends on deployment history, a CREATE2 address can be computed by anyone, at any time, before the contract exists.

What Uniswap V3 buys with it

The factory deploys each pool with CREATE2, using keccak256(abi.encode(token0, token1, fee)) as the salt. Every pool's address is therefore a deterministic function of its two tokens and its fee tier.

This turns a storage lookup into a computation. A router that needs the pool for a given pair and fee does not have to call the factory and pay for an external call and a cold storage read — it derives the address locally from three values it already has.

More importantly, it works in the other direction. Given an address, anyone can determine which pool it claims to be. That inversion is what makes V3's callback security possible.

The callback check it enables

Uniswap V3 pools call back into the caller mid-swap to demand payment. The callback is a public function that transfers tokens, so it must establish that the caller really is a pool.

CREATE2 makes the check one comparison: derive the expected pool address from the token pair and fee, and require that msg.sender equals it. See callback validation for why this is not circular reasoning even though the tokens and fee arrive as attacker-suppliable calldata.

Without CREATE2, the equivalent check would be a factory lookup on every callback — an external call inside the hot path of every swap.

The constraint it imposes

Because the address depends on the init code hash, the pool's creation bytecode is frozen. Any change to the pool contract, including one produced by a different compiler version or optimizer setting, produces different addresses for pools that have not yet been deployed, and breaks every hard-coded POOL_INIT_CODE_HASH constant in the periphery.

This is a recurring source of confusion in forks: the periphery contracts embed the hash as a constant, and a fork that recompiles the core without regenerating that constant will derive addresses no pool occupies. The failure is loud in tests and subtle in production, where it manifests as a callback check that rejects every genuine pool.

CREATE2 also enables address mining — searching salts for an address with desired properties — which matters wherever an address's leading bytes carry meaning.

Need expert guidance on CREATE2?

Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.

Get a Quote