CREATE2 Security Guide: Deterministic Contract Addresses, Wallet Drain Scams, and Deployment Risk
A CREATE2 smart contract uses a deterministic deployment rule that allows its future address to be calculated before the contract is deployed. The core security question is not whether CREATE2 is good or bad, but whether users can independently verify the deployer, salt, initialization code, constructor inputs, factory permissions, future runtime behavior, and any approvals or funds connected to the predicted address before code appears there.
TL;DR
- CREATE2 makes a contract address predictable before deployment. The result depends on the deploying contract, a 32-byte salt, and the hash of the complete initialization code.
- A predicted address is not proof of safe future code. The address commits to specific initialization code, but users still need to understand what that code deploys, which constructor inputs are included, and whether external state influences the final runtime.
- Legitimate uses include counterfactual wallets, factory deployments, deterministic protocol components, escrow addresses, account abstraction, and consistent multi-step workflows.
- An empty address can already have dangerous approvals. A user can approve an undeployed predicted address as a token spender. Code deployed later at that address may be able to use the existing allowance.
- Sending funds to a predicted address is a trust decision. The funds may remain inaccessible until deployment, become controlled by later code, or become permanently stranded if deployment never happens.
- The factory matters as much as the address. A public factory, mutable deployer, weak access control, reusable salt, or misleading initialization code can change who controls deployment and how the final contract behaves.
- CREATE2 does not automatically make a contract immutable. The deployed contract may be a proxy, reference an upgradeable implementation, read mutable registries, or grant powerful administrative roles.
- Modern selfdestruct rules reduce traditional metamorphic redeployment patterns on Ethereum, but legacy contracts and other EVM networks still require chain-specific analysis.
An undeployed deterministic address can receive ETH, hold token allowances, appear in signed messages, be referenced by another contract, or be presented by a phishing interface as a future wallet or protocol component. Risk analysis must examine what can be deployed there, who controls the deployment path, and what authority the address already possesses.
Deterministic-address review requires code verification and wallet context
Start with the TokenToolHub smart contract verification guide to understand how deployed bytecode should be matched with source code. For a predicted address, extend that process to the factory, salt, initialization code, constructor arguments, and expected deployment transaction. When deployer, treasury, phishing, or contract-funding relationships need additional context, Nansen can help analysts examine labeled entities and related wallet movement. Address labels are supporting context, not proof that a future deployment is safe.
What CREATE2 is and why deterministic deployment matters
Smart contracts are normally deployed through either the EVM CREATE opcode or the CREATE2 opcode. Both create a new contract account, execute initialization code, and store the resulting runtime bytecode at the new address. The key difference is how the address is calculated.
A traditional CREATE deployment derives the new address from the deployer's address and deployment nonce. The address therefore depends on how many contract-creation transactions the deployer has already performed. Predicting it can be possible, but the prediction requires knowing and preserving the relevant nonce sequence.
CREATE2 uses a different formula. The future address depends on the deploying contract's address, a salt selected for the deployment, and the hash of the complete initialization code. Because these inputs can be known before deployment, the contract address can be calculated in advance.
This creates a deterministic contract address. The same deployer, same salt, and same initialization code produce the same predicted address, provided deployment is still possible at that address. Changing any one of those inputs changes the result.
address = last20bytes(keccak256(0xff ++ deployer ++ salt ++ keccak256(init_code)))
The fixed 0xff prefix separates the CREATE2 calculation domain from ordinary address-generation patterns. The deployer is the contract executing the opcode, not necessarily the externally owned wallet that submitted the transaction. The salt is a 32-byte value. The initialization-code hash commits to the exact byte sequence executed during contract creation.
After hashing those values together, the final 20 bytes of the result become the predicted contract address. The contract does not need to exist for wallets, interfaces, factories, and other contracts to calculate and reference that address.
The initialization code is not the same as runtime code
Initialization code is temporary creation logic. The EVM executes it during deployment. It can validate constructor arguments, initialize values, interact with other contracts, and return the runtime bytecode that remains at the new address.
CREATE2 commits to the hash of this initialization code, including constructor arguments appended to it. It does not simply hash the final runtime bytecode. This distinction matters because two deployments using the same contract source but different constructor arguments normally have different initialization-code hashes and different predicted addresses.
It also means that a predicted address should not be evaluated using runtime code alone. Reviewers need the complete creation bytecode, encoded constructor values, factory behavior, and any state-dependent logic executed during construction.
CREATE2 Address Flow: deployer, salt, bytecode hash, and final deployment
The visual below shows the inputs that produce a predicted address. It also highlights the most important review boundary: predicting an address is a mathematical step, while deciding whether the future deployment is safe requires understanding the initialization code and deployment authority.
Deployer contract
The address of the factory or contract that executes CREATE2 becomes part of the calculation.
Salt
A 32-byte salt distinguishes deployments and helps make the address deterministic.
Initialization code
The hash includes the creation bytecode and encoded constructor arguments.
Predicted address
The future contract address can be calculated before any runtime code exists there.
Deployment
The factory executes the committed initialization code and stores the returned runtime code.
A simple mental model for deterministic contract addresses
Think of CREATE2 as a sealed deployment recipe. The recipe contains three defining ingredients: the factory address, a salt, and the initialization code. Hashing the complete recipe produces a destination address.
Anyone with the same recipe can calculate the same destination. However, calculating the destination does not deploy the contract. The factory must still execute the deployment successfully.
The address behaves like a reserved destination only in a practical sense, not as an exclusive blockchain reservation. The EVM does not mark it as reserved merely because someone calculated it. Deployment succeeds only when the correct factory executes CREATE2 with the correct inputs and the target address is available under the network's contract-creation rules.
This mental model supports four important conclusions:
The inputs define the address
Changing the factory, salt, initialization code, or constructor arguments changes the predicted address.
The address can exist before code
It can receive ETH or become an approved spender even while its code size is zero.
The factory controls execution
The contract appears only when the factory successfully executes the deployment recipe.
The recipe needs inspection
A trustworthy prediction requires independently verifying every address-calculation input.
Legitimate CREATE2 deployment patterns
CREATE2 is a foundational deployment primitive. It is widely useful because predictable addresses allow several actions to be coordinated before the corresponding contract exists. The security risk comes from weak verification or deceptive use, not from deterministic deployment itself.
Counterfactual smart contract wallets
A counterfactual wallet is a smart account whose address can be calculated before deployment. A user or application can display the address, receive assets there, or reference it in another workflow before paying the gas required to deploy the wallet.
Later, a trusted account factory deploys the wallet at the predicted address using the expected initialization code. The deployed account recognizes the intended owner or signing policy, making the previously received assets accessible through the wallet's logic.
This approach can improve onboarding because users do not need to deploy an account before receiving funds. It also supports account abstraction workflows where wallet creation occurs during the user's first operation.
The safety requirement is strict. Users must verify the account factory, ownership parameters, salt derivation, module configuration, recovery settings, and initialization code. Sending assets to a predicted wallet address without confirming those inputs can give future control to the wrong contract or leave funds inaccessible.
Factory contracts and repeatable deployments
Factories use CREATE2 to deploy predictable pools, vaults, wallets, escrows, clones, and application modules. A protocol can calculate the address of a future component before the component is deployed and then configure other contracts to recognize it.
Deterministic factories can improve consistency. Front ends can calculate addresses without relying entirely on an off-chain deployment database. Other contracts can verify that an address corresponds to a known factory and deployment recipe.
The factory must still be reviewed carefully. A factory may allow arbitrary users to select salts or initialization code. It may deploy upgradeable proxies rather than fixed logic. It may use an owner-controlled implementation registry. It may encode ownership based on the transaction caller. These choices determine whether the predicted deployment is safe.
Counterfactual escrow and payment addresses
A payment application can calculate an escrow address before deploying the escrow. Funds can be sent to the predicted address, and the escrow can be deployed later when settlement conditions are ready.
This can reduce unnecessary deployment costs and allow the same address to be shared early in a transaction lifecycle. It can also create severe recovery risk if the deployment recipe is wrong, the factory disappears, the salt is miscalculated, or the deployed contract does not grant control to the expected participants.
Funding an undeployed address should therefore be treated like funding a contract, not like transferring to an ordinary wallet. The future runtime code determines how the assets can move.
Predictable protocol components
Decentralized exchanges, lending systems, bridges, application routers, and modular protocols may need component addresses before all components are deployed. CREATE2 allows those addresses to be determined from agreed inputs.
Predictability can simplify integration and reduce configuration mistakes. It can also make deployment verification easier when users can independently reproduce the address calculation.
The calculation proves only that a particular initialization-code hash corresponds to the address under a particular factory and salt. It does not prove that the factory will deploy the contract, that the initialization code is safe, or that the deployed contract cannot later change behavior through a proxy or external registry.
Minimal proxies and clone factories
Clone factories deploy small proxy contracts that delegate execution to an implementation. CREATE2 can make each clone address predictable. The initialization code may be short and repeatable, while the salt differentiates user accounts, markets, vaults, or campaigns.
Reviewers must inspect both layers. The clone's predicted address depends on its initialization code, but its behavior depends on the implementation it delegates to. If the implementation address is mutable, upgradeable, or selected from a registry, the future behavior may not be fixed by the predicted clone address.
Solidity CREATE2 example: predicting and deploying a contract
The simplified example below demonstrates the core mechanism. A factory calculates the future address from a salt and creation bytecode, then deploys the contract with CREATE2. It is educational code, not a complete production factory.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract DeterministicVault {
address public immutable owner;
uint256 public immutable vaultId;
constructor(address initialOwner, uint256 id) {
require(initialOwner != address(0), "Invalid owner");
owner = initialOwner;
vaultId = id;
}
}
contract DeterministicVaultFactory {
event VaultDeployed(
address indexed vault,
address indexed owner,
uint256 indexed vaultId,
bytes32 salt
);
function creationCode(
address owner,
uint256 vaultId
) public pure returns (bytes memory) {
return abi.encodePacked(
type(DeterministicVault).creationCode,
abi.encode(owner, vaultId)
);
}
function predictVault(
address owner,
uint256 vaultId,
bytes32 salt
) public view returns (address predicted) {
bytes32 initCodeHash = keccak256(
creationCode(owner, vaultId)
);
bytes32 digest = keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
salt,
initCodeHash
)
);
predicted = address(uint160(uint256(digest)));
}
function deployVault(
address owner,
uint256 vaultId,
bytes32 salt
) external returns (address vault) {
bytes memory code = creationCode(owner, vaultId);
assembly {
vault := create2(
0,
add(code, 0x20),
mload(code),
salt
)
}
require(vault != address(0), "Deployment failed");
emit VaultDeployed(vault, owner, vaultId, salt);
}
}
The predicted address changes when the factory address, owner, vault ID, salt, or creation bytecode changes. Constructor arguments are encoded into the initialization code, so they are part of the address commitment.
What the code example proves
The predictVault function reproduces the CREATE2 formula. A user can call it before deployment and compare the result with a locally calculated address. When deployVault later uses the same initialization code and salt, the contract should appear at that predicted address.
The example also shows why users must verify constructor arguments. The owner and vault ID are encoded into the initialization code. Changing the owner creates a different predicted address. A phishing interface that displays one owner but submits another constructor value would produce a different address.
What the example does not prove
It does not prove that a production factory is safe. A real factory may include access control, fees, implementation registries, proxy deployments, callbacks, token transfers, arbitrary initialization data, or administrator-controlled settings.
It also does not guarantee that the final runtime behavior is permanently fixed. The deployed contract could be a proxy. It could call a mutable registry. It could rely on another contract whose logic changes. It could grant an administrator broad permissions.
Why a predicted address can be risky before code exists
Blockchain interfaces often treat code presence as a major distinction. An address with no bytecode may be displayed like an ordinary wallet. A user may check a block explorer, see no contract source, and assume the address cannot perform complex actions.
CREATE2 weakens that assumption. The address can be connected to a known future deployment recipe. It may become a contract later without changing the address.
This matters because several forms of authority can exist before deployment. ERC-20 approvals can designate the address as a spender. Permit signatures can authorize it. Another contract can store it as an operator or trusted module. Users can send ETH or tokens to it. A protocol can recognize it as a future account.
Once code is deployed, the address can exercise whatever authority was granted, subject to the relevant token and protocol rules. The risk existed when the approval, signature, or funding decision was made, even though no runtime code was visible at that moment.
An empty predicted address can later become executable code. Review the transaction permission itself, not only whether the spender currently has verified source code.
How CREATE2 can support wallet drain approval setups
Token approvals are permissions recorded in the token contract's storage. When a user calls approve(spender, amount), the token records that the spender address may transfer tokens up to the approved limit through transferFrom.
The token contract does not generally require the spender to contain code when approval is granted. A user can approve an externally owned account, an undeployed address, or a deterministic address that will become a contract later.
This creates a scam pattern. A malicious interface asks the user to approve a spender address. At the time of signing, the address has no code. The interface or attacker may claim this proves the approval is harmless. Later, the attacker's factory deploys code at that predicted address. The new contract can attempt to use the existing allowance.
CREATE2 does not create the approval vulnerability. The dangerous permission already came from the user's signature or transaction. CREATE2 helps the attacker separate the permission stage from the code-deployment stage, making the spender harder to analyze at the moment of approval.
Why block-explorer checks can miss the risk
A block explorer can accurately report that the address has no code. That observation describes the current state. It does not prove that the address will remain code-free.
If the address is derived from a CREATE2 factory, the future code may already be predictable. Without the factory, salt, and initialization code, an ordinary user may not know what is planned.
Users should therefore inspect the approval amount, token, spender, expiration or revocation options, transaction origin, and application legitimacy. A code-free spender should not receive unlimited approval merely because no contract is visible.
Permit signatures and delayed deployment
Some tokens support off-chain permit signatures. A user signs structured data authorizing a spender, and another party later submits the signature on-chain. Depending on the permit standard and token implementation, the spender can be an undeployed deterministic address.
The risk can be harder to recognize because the user may not submit an on-chain approval transaction directly. The signature itself creates or enables the permission when relayed.
Not every dangerous signature is a replay attack. Replay risk concerns whether a valid signature can be reused outside its intended nonce, chain, contract, deadline, or domain. CREATE2 risk concerns what address receives authority and what code may appear there. The two issues can overlap, so users should understand both the spender and the signature's domain protections. The TokenToolHub signature replay attacks guide explains the separate replay dimension.
Unlimited approvals increase the blast radius
If a user approves only the required amount, the maximum direct exposure is narrower. An unlimited approval can remain active long after the original website interaction. Future code at the predicted spender address may encounter a wallet that has accumulated more tokens since the approval was signed.
The TokenToolHub crypto approval risks guide explains why users should verify spenders, limit amounts, review old permissions, and revoke access that is no longer required.
CREATE2 wallet drain setup: permission before deployment
The sequence below shows the security problem without relying on exploit code. The key lesson is that authority can be granted to an address before its executable behavior is visible.
Predicted spender
An attacker or deceptive application calculates a future contract address through a CREATE2 factory.
User grants permission
The wallet approves the predicted address or signs a permit authorizing it as spender.
Code appears later
The factory deploys executable code at the exact address that already holds approval.
Allowance is used
The deployed contract can interact with the token according to the previously granted permission.
This separation can defeat a simple review method that checks only whether the spender is currently a contract. It does not defeat careful transaction review. The approval request still identifies the spender address, token, and amount. The application requesting the permission still needs to be trusted or independently verified.
Phishing and deception patterns involving deterministic addresses
CREATE2 can support several deception patterns because the address is known before deployment. The following patterns are risk indicators, not evidence that every deterministic deployment is malicious.
The empty spender claim
A website tells the user that an approval is safe because the spender has no contract code. This is an invalid security claim. The address may be a predicted deployment destination.
Users should not approve an unknown spender based on code absence. The correct checks include application origin, transaction simulation, approval amount, token value, spender history, factory relationship, and whether the permission is necessary.
The future wallet funding request
A service tells the user to send ETH or tokens to a smart wallet that will be deployed later. Counterfactual wallets can work legitimately, but the user must verify the factory and ownership configuration.
A fraudulent service can provide a predicted address whose future contract grants control to the attacker. It can also provide an address that can never be deployed through the claimed factory, causing assets to remain stranded.
Lookalike deterministic addresses
Attackers can search salts to produce addresses with selected visual prefixes or suffixes. A lookalike address may resemble a trusted protocol component or a familiar wallet when users compare only a few characters.
Deterministic vanity generation does not let an attacker copy an arbitrary complete address, but it can create enough visual similarity to support address poisoning or interface deception. Users should verify the complete address through trusted application paths rather than matching the first and last few characters.
Fake predeployment verification
A project may show source code for a contract it claims will be deployed at a predicted address. The address calculation may use different constructor arguments, a different factory, a different salt, or different creation bytecode.
Source publication alone is not enough. Reviewers should independently reconstruct the complete initialization code and reproduce the predicted address. After deployment, the runtime bytecode should be verified against the expected result.
Deployment after trust accumulation
An undeployed address may receive small test transfers, become listed in documentation, appear in allowlists, or accumulate approvals over time. Malicious code can be deployed only after enough value or trust has collected.
Monitoring systems should flag newly deployed code at addresses that already hold significant balances, allowances, operator permissions, or protocol roles.
What users should verify before funding a predicted address
Sending assets to a predicted contract address is fundamentally different from sending assets to an ordinary wallet controlled by a known private key. Before deployment, no private key controls the address in the ordinary EOA sense. Access to the assets depends on the code that will later be deployed and the authority that code recognizes.
Predicted-address funding checklist
- Verify the factory address: Confirm the exact contract that will execute CREATE2.
- Verify the factory source: Check whether the deployed factory bytecode matches the reviewed source code.
- Confirm the salt: Record the full 32-byte value and how it is derived.
- Reconstruct initialization code: Include creation bytecode and all encoded constructor arguments.
- Recalculate the address independently: Do not rely only on the project's interface.
- Verify future ownership: Determine which address, key, multisig, or governance contract will control the deployment.
- Check recovery logic: Confirm how ETH and tokens can be withdrawn after deployment.
- Check deployment permissions: Determine whether anyone can deploy, only an administrator can deploy, or a signature is required.
- Assess front-running risk: Confirm whether another party can deploy the same recipe before the intended transaction.
- Inspect external dependencies: Check registries, modules, implementations, or oracles used during construction.
- Confirm proxy behavior: Determine whether the predicted contract will be upgradeable.
- Check network selection: The same factory and salt on another chain may produce the same address but a different deployment state.
- Understand failure recovery: Determine what happens if deployment never occurs or the factory becomes unusable.
- Start with limited value: Avoid funding an unverified prediction with assets you cannot recover.
Funding does not guarantee deployment
A predicted address can receive ETH and tokens even if the contract is never deployed. The blockchain does not automatically create the contract because funds arrived.
If the factory cannot deploy the expected code, the assets may be stranded. Common causes include an incorrect salt, wrong constructor arguments, a factory that is paused or destroyed, incompatible initialization code, insufficient deployment gas, an occupied target address, or loss of the authority required to initiate deployment.
Deployment does not guarantee recovery
Even when the contract appears successfully, its runtime logic may not provide the expected withdrawal path. Ownership can be assigned incorrectly. Initialization can fail or leave the contract in an unusable state. Tokens may require special transfer handling. An upgradeable wallet may point to an unsafe implementation.
The correct verification target is the complete recovery path, not only whether code eventually appears.
What users should verify before signing for a predicted address
A signature can create authority without moving funds immediately. Approvals, permits, operator permissions, account-abstraction operations, and protocol-specific authorizations may all designate an address that does not yet contain code.
Pre-signing checklist
- Identify the permission type: Determine whether the request is a token approval, permit, operator approval, login message, order, account action, or protocol authorization.
- Read the spender or verifying address: Confirm the complete address, not a shortened display.
- Check the amount: Avoid unlimited permission when a limited amount is sufficient.
- Check the token: Confirm the exact asset contract and network.
- Check the chain ID: Ensure the signature cannot be used on an unintended network.
- Check the deadline: Prefer permissions with a reasonable expiration where supported.
- Check nonce protection: Confirm whether the signature has proper single-use or ordered nonce controls.
- Verify the application origin: Do not trust a signature request opened from an unsolicited message or advertisement.
- Simulate when possible: Review the likely state change and affected assets.
- Investigate empty spenders: Treat code absence as a reason for deeper review, not reassurance.
- Revoke unnecessary access: Remove permissions after the intended action is complete.
Factory contract risks that change CREATE2 safety
The factory is part of every CREATE2 address calculation. It is also the component that executes the deployment. A safe-looking initialization-code hash cannot compensate for an untrusted factory.
Arbitrary initialization code
Some factories accept arbitrary creation bytecode from the caller. This flexibility can be useful for general deployment infrastructure. It also means that the factory's reputation does not automatically transfer to every contract it deploys.
A known factory address may deploy safe contracts, malicious contracts, proxies, wallets, or experimental code. Review the exact initialization-code hash for the specific address.
User-controlled salts
Allowing users to select salts is common. It supports unique deterministic addresses and vanity generation. The factory should define what happens when two users choose the same salt.
Because initialization code also affects the address, the same salt can produce different addresses when code or constructor values differ. A factory may additionally namespace salts by hashing the caller's address with the supplied salt.
Users should verify the actual salt transformation. The value entered in an interface may not be the final 32-byte salt passed to CREATE2.
Front-running and public deployment
If any account can call the factory with the same public recipe, another party may be able to submit the deployment first. Whether this creates harm depends on how ownership and initialization are bound.
If the intended owner is encoded directly into initialization code, an early deployment of the same recipe may still produce a contract owned by the intended user. The front-runner pays the gas but may not gain control.
If ownership depends on msg.sender inside the factory or an unsafe callback, the first caller may influence control. Factories should bind ownership and initialization to explicit authenticated data rather than assuming the transaction initiator is always the intended owner.
Mutable implementation registries
A factory can deploy proxies that read an implementation address from a registry. The predicted proxy address may remain constant while the registry owner changes the logic used by the proxy.
In this architecture, verifying the CREATE2 calculation proves the deployment destination, not the permanent behavior. Review registry ownership, implementation upgrades, timelocks, emergency powers, and events.
Factory upgrades
A factory may itself be upgradeable. Its address remains part of the CREATE2 formula, but its deployment logic can change. A predicted address calculated under one implementation may still be mathematically valid, while the upgraded factory refuses to deploy, changes salt derivation, adds fees, modifies initialization code, or grants different ownership.
Users funding a long-term counterfactual address should understand whether the factory can change and who controls that upgrade.
Why a deterministic address does not guarantee deterministic behavior
CREATE2 commits to the initialization-code bytes. It does not directly guarantee that every future behavior of the deployed system is immutable.
Constructor logic can read external state
Initialization code can call other contracts, inspect external configuration, or use deployment-time state. The same initialization-code bytes may produce runtime behavior influenced by the environment in which deployment occurs.
This is an advanced but important distinction. A reproducible address calculation proves which initialization-code bytes will execute. Reviewers must still determine what those bytes do under the expected deployment conditions.
The deployment may create a proxy
A deterministic address can belong to a transparent proxy, UUPS proxy, beacon proxy, minimal clone, or custom delegatecall router. The proxy's initialization code may be fixed while its implementation can change later.
Use the TokenToolHub hidden backdoors guide to investigate whether an owner, upgrader, module manager, or registry can alter behavior after users begin trusting the address.
External dependencies can change
A fixed contract can call an external oracle, router, registry, token, bridge, or implementation. If those dependencies are mutable or upgradeable, the practical behavior of the CREATE2 deployment can change without redeploying the contract.
Deterministic address verification should therefore be combined with dependency mapping. The predicted contract may be only one layer in a larger control system.
Address collisions, redeployment, and contract existence rules
Calculating a CREATE2 address does not guarantee that deployment will succeed. Contract creation fails when the destination already has blocking account state under the EVM's collision rules, including existing code or a nonzero nonce.
This prevents a factory from simply overwriting an active contract with a new deployment. A successful CREATE2 deployment requires an address that is available for creation.
Salt reuse does not always mean address reuse
The salt is only one input. The same factory can use the same salt with different initialization code and produce different addresses. Conversely, the same factory, salt, and initialization-code hash always target the same address.
Review tools should display all three decisive values rather than describing the salt as if it uniquely identifies the address.
Selfdestruct and historical metamorphic contracts
Earlier Ethereum behavior allowed a long-lived contract to execute SELFDESTRUCT and have its code and storage removed at the end of the transaction. Some metamorphic patterns combined that behavior with deterministic deployment to place different runtime code at a familiar address.
Modern Ethereum rules significantly restrict this pattern. Under EIP-6780, a contract that was not created in the same transaction generally retains its code and storage after executing SELFDESTRUCT. The address therefore remains occupied, preventing the traditional multi-transaction delete-and-redeploy sequence.
The TokenToolHub selfdestruct guide explains the historical behavior, forced ETH transfers, same-transaction exception, and why chain-specific rules still matter.
Do not assume identical behavior across every EVM network
EVM-compatible networks can activate protocol changes at different times or implement different execution rules. A CREATE2 and selfdestruct conclusion based on modern Ethereum may not apply identically to another network.
Multi-chain protocols should publish deployment assumptions for each chain. Analysts should confirm network rules, factory bytecode, implementation addresses, and deployment transactions separately.
TokenToolHub Research Note: an address can appear safe before dangerous code exists
Traditional contract review often begins with deployed bytecode. CREATE2 introduces a predeployment risk stage in which an address can already hold assets, allowances, signatures, protocol permissions, or user trust while its runtime code remains absent.
This creates an asymmetry. The user makes a present decision based on future code. The factory controller, application, or attacker may possess more information about that future deployment than the user can see in a wallet confirmation.
The most useful safety rule is therefore temporal: evaluate not only what an address is now, but also what it is authorized to become. For predicted addresses, security review begins before deployment and continues after code appears.
This insight also changes how monitoring systems should classify risk. A newly deployed contract can be immediately dangerous if the address already possesses token allowances or account permissions. Waiting for post-deployment transaction history may be too late.
A stronger monitoring model links three timelines:
Permission timeline
When did the address receive approvals, permits, operator rights, balances, allowlist status, or protocol roles?
Deployment timeline
When was code deployed, through which factory, with which salt and initialization-code hash?
Execution timeline
What did the new contract do immediately after deployment, and which pre-existing permissions did it use?
Due diligence workflow for a CREATE2 deployment
A practical review starts with the displayed address and works backward to the complete deployment recipe. It then works forward from the recipe to the expected runtime behavior and permission model.
Identify the claim
Determine whether the address is presented as a wallet, escrow, vault, spender, pool, proxy, or future protocol component.
Find the factory
Locate the exact contract expected to execute CREATE2 and verify its deployed source code.
Rebuild the recipe
Collect the salt, creation bytecode, constructor arguments, and any factory-side salt transformation.
Recalculate the address
Independently reproduce the predicted address and compare every byte with the displayed destination.
Review runtime behavior
Determine ownership, withdrawal paths, proxy logic, external dependencies, permissions, and upgrade controls.
Check existing authority
Search for balances, approvals, permits, operator rights, allowlists, and protocol references tied to the address.
Monitor deployment
Confirm the deploying transaction, emitted events, runtime bytecode, initialization, and immediate follow-on activity.
Verify final control
Confirm the actual owner, implementation, modules, recovery path, and any administrative changes after deployment.
Check the factory transaction history
A reputable factory may have a consistent history of deploying known account or protocol code. A newly deployed factory with no verified source, unusual funding, or links to phishing wallets deserves greater caution.
Wallet analytics can support this investigation. Nansen can help identify labeled deployers, treasury wallets, exchanges, and connected addresses where coverage exists. Direct bytecode, transaction, and event analysis remains necessary.
Monitor the predicted address before deployment
Track incoming ETH, token transfers, approvals, operator permissions, and references from other contracts. Significant authority accumulating at an empty address is a reason to identify the expected deployment recipe.
If code appears unexpectedly, compare the deployment transaction with the claimed factory and initialization-code hash immediately.
Verify after deployment
Once deployed, inspect the runtime bytecode and source verification. Confirm ownership, proxy implementation, initialization state, modules, allowances, token balances, and any transactions executed in the same block.
Attackers may deploy and use a contract quickly, leaving little time between code appearance and asset movement. Predeployment monitoring is therefore more valuable than relying only on later contract history.
CREATE2 source-code review checklist for non-experts
Non-expert readers do not need to audit every assembly instruction to ask useful questions. The checklist below focuses on the elements that determine the address and the authority behind the deployment.
30-point CREATE2 review checklist
- Confirm CREATE2 is actually used: Search for
create2, assembly deployment, deterministic-clone functions, and address-computation helpers. - Identify the deploying contract: The factory address is part of the predicted address.
- Verify factory bytecode: Do not rely on a repository that may not match the deployed factory.
- Find the salt source: Determine whether it is user-supplied, sequential, random, hashed, namespaced, or administrator-controlled.
- Check salt transformation: The factory may hash the caller, chain ID, token, or other values with the displayed salt.
- Obtain creation bytecode: Runtime code alone is not enough for address calculation.
- Include constructor arguments: They normally change the initialization-code hash.
- Reproduce the init-code hash: Confirm the exact bytes used by the factory.
- Recalculate the final address: Compare the complete address, not a shortened representation.
- Check contract existence: Determine whether code or a nonzero nonce already blocks deployment.
- Review deployment access: Identify who can call the factory and what authorization is required.
- Assess front-running: Determine whether another caller can deploy the same recipe first.
- Verify ownership assignment: Ownership should be explicitly bound to intended data, not unsafe caller assumptions.
- Check initialization: Confirm that the contract cannot remain uninitialized or be initialized by the wrong account.
- Identify proxy patterns: Determine whether the deployment creates a proxy, clone, beacon proxy, or modular router.
- Find implementation controls: Review upgrade admins, registries, beacons, and module managers.
- Review external constructor calls: Initialization code may depend on mutable contracts or deployment-time state.
- Check value forwarding: Determine whether ETH is sent during deployment and where it can move.
- Check token-recovery logic: Confirm how assets sent before deployment become accessible.
- Review failure handling: Determine what happens when CREATE2 returns the zero address or constructor execution reverts.
- Check repeated deployment assumptions: Modern selfdestruct semantics may invalidate delete-and-redeploy designs.
- Review chain compatibility: Confirm behavior on every target network.
- Check emitted events: Deployment events should identify the created address, salt, owner, and relevant configuration.
- Review approvals to predicted addresses: Search token allowances and operator permissions before deployment.
- Inspect signed authorizations: Check permit domains, nonces, deadlines, chain IDs, and spender addresses.
- Check address-display risks: Do not trust only prefixes, suffixes, labels, or vanity similarities.
- Confirm deployment timing: Determine whether users are expected to fund or approve the address before code appears.
- Check administrative changes: Review whether the factory or deployment registry can be upgraded.
- Monitor post-deployment activity: Watch initialization, approval use, token movement, and ownership changes.
- Separate predictability from safety: A reproducible address can still lead to unsafe or upgradeable code.
CREATE2 deployment risk matrix
The matrix below helps classify deterministic deployments. It is not a replacement for code review, but it separates stronger verification signals from conditions that require caution.
| Review factor | Lower-risk signal | Needs caution | Dangerous signal |
|---|---|---|---|
| Factory verification | Factory source is verified, stable, and independently reviewed. | Source is verified but the factory is upgradeable or highly flexible. | Factory is unverified, newly deployed, or controlled by unknown accounts. |
| Address calculation | Users can independently reproduce the address from published inputs. | Some inputs are available but salt transformation or constructor data is unclear. | Users are asked to trust a displayed address without reproducible inputs. |
| Future ownership | Owner, signers, and recovery policy are encoded transparently. | Ownership depends on a registry or administrator-controlled setup. | Attacker-controlled or undisclosed addresses receive control. |
| Predeployment funding | Limited value is sent after independent factory and code verification. | Significant funds are sent before deployment with partial recovery evidence. | Users are pressured to fund an unexplained empty address. |
| Predeployment approval | No token permissions are granted before code verification. | Limited approval is granted to a well-documented counterfactual account. | Unlimited approval is granted to an unknown empty spender. |
| Runtime behavior | Fixed, verified runtime code with narrow permissions. | Proxy or external dependencies exist with transparent governance. | Hidden upgrade, delegatecall, registry, or arbitrary-call authority exists. |
| Deployment access | Public deployment cannot change intended ownership or configuration. | Public deployment may affect timing but not control. | Front-running can redirect ownership or alter initialization. |
| Address presentation | Complete address is verified through trusted application paths. | Users rely partly on labels or shortened displays. | Lookalike prefixes, copied labels, or unsolicited addresses are used. |
| Monitoring | Funding, approvals, deployment, and code changes are actively monitored. | Only post-deployment activity is monitored. | No alert exists when code appears at an authorized address. |
Practical CREATE2 security scenarios
Scenario one: a legitimate counterfactual wallet
A wallet provider publishes a verified account factory. The future address is derived from the factory, a salt tied to the user, and initialization code that encodes the user's owner key and recovery policy.
The user independently reproduces the address, sends a small amount of ETH, and later deploys the wallet through the factory. The deployed runtime code is verified, ownership matches the expected key, and the wallet can recover the prefunded assets.
The risk is manageable because the complete recipe is transparent and independently reproducible.
Scenario two: an unlimited approval to an empty spender
A phishing interface asks a user to approve an address for unlimited token spending. The address has no code, and the interface claims that this makes it harmless.
The address is actually a CREATE2 prediction controlled by the scammer's factory. After the approval is recorded, the scammer deploys a contract at the address and attempts to use the allowance.
The primary failure occurred when the user approved an untrusted spender. CREATE2 made the spender's future behavior less visible at the time of signing.
Scenario three: funding an incorrectly calculated escrow
A marketplace displays a predicted escrow address. The front end uses one constructor value, while the factory deployment transaction uses another. The resulting initialization-code hash differs, so the deployed contract appears at a different address.
Assets sent to the original prediction remain at an undeployed address. If the expected recipe can no longer be deployed or would assign control incorrectly, recovery may be impossible.
Independent address reproduction would have revealed the mismatch before funding.
Scenario four: a deterministic proxy with mutable implementation
A protocol deploys vault proxies through CREATE2. Users verify each predicted proxy address and assume this guarantees stable behavior.
The proxies delegate to an implementation selected by an administrator-controlled beacon. The beacon owner later changes the implementation. The proxy addresses remain the same, but withdrawal and fee logic change.
CREATE2 provided predictable addresses, not immutable execution. Users also needed to review the beacon and upgrade authority.
Scenario five: a front-run deployment with unsafe owner assignment
A public factory calculates a predicted address from a salt and generic initialization code. The factory assigns ownership based on the transaction caller rather than encoding the intended owner into the committed initialization code.
Another account observes the planned transaction and calls the factory first. The deployed contract appears at the expected address but recognizes the front-runner as owner.
A safer design binds ownership to authenticated deployment data or includes the intended owner directly in the initialization-code commitment.
Scenario six: a lookalike protocol address
An attacker searches salts until a CREATE2 prediction resembles a trusted router address in its visible prefix and suffix. A phishing interface displays only shortened addresses.
Users approve or fund the lookalike address because it appears familiar. The complete address differs.
Address familiarity is not verification. Wallets and interfaces should display enough information to distinguish the exact destination and application origin.
Wallet safety when interacting with deterministic deployments
Secure custody does not make an unsafe approval safe. A hardware wallet can protect private keys and display transaction details on a separate screen, but the user must still understand the spender, amount, network, and permission being authorized.
Hardware wallets such as Ledger and SafePal can support wallet separation. Long-term holdings can remain isolated from wallets used for experimental applications, token approvals, and counterfactual account testing.
This reduces the value exposed to a malicious spender, but it does not replace approval review. A compromised interaction wallet can still lose every asset covered by its permissions.
The signing device protects the key. Transaction review protects the authorization decision. CREATE2 analysis explains what the authorized address can become later. All three layers solve different security problems.
Connecting CREATE2 to token safety review
A token contract does not need to use CREATE2 for token holders to face deterministic-address risk. The relevant CREATE2 contract may be a spender, router, vault, bridge, exchange module, reward distributor, or malicious contract approved by token holders.
A token review should therefore inspect external permissions and integrations, not only the token source. The TokenToolHub Token Safety Checker can support an initial review of token permissions and contract characteristics. Automated analysis should be followed by direct source, proxy, approval, and deployment verification where meaningful value is exposed.
Questions to ask about a token-related predicted address
- Is the address receiving token approvals before deployment?
- Is it expected to become a router, vault, distributor, or staking contract?
- Which factory will deploy it?
- Does the initialization code grant transfer, sweep, mint, burn, or administrative authority?
- Will the deployed contract be a proxy or delegatecall router?
- Can a token owner or protocol administrator change the recognized address later?
- Does the address already hold tokens that could become accessible after deployment?
CREATE2 and hidden backdoor analysis
CREATE2 is not itself a backdoor. It becomes part of backdoor analysis when a project conceals what will be deployed, uses deterministic addresses to accumulate permissions before code review, or combines a fixed address with mutable implementation control.
A project may advertise a stable deterministic address while an administrator controls the implementation registry behind it. A factory may deploy different code based on hidden configuration. A predicted address may receive approvals before the code is disclosed. A public interface may claim the address is safe because it is currently empty.
Use the hidden backdoors in smart contracts guide to evaluate upgrade functions, privileged calls, mutable registries, arbitrary external calls, asset sweeps, and concealed permission paths.
Monitoring deterministic deployments
Effective monitoring begins before deployment. A useful CREATE2 monitoring system should connect predicted addresses with their factories and track permissions or assets that accumulate before code appears.
CREATE2 monitoring checklist
- Record prediction inputs: Factory, salt, initialization-code hash, constructor values, network, and expected owner.
- Watch address funding: Track ETH, tokens, NFTs, and protocol shares sent before deployment.
- Watch approvals: Detect ERC-20 allowances and operator permissions granted to the address.
- Watch permit activity: Track submitted signatures and relevant nonce changes where possible.
- Watch factory changes: Monitor upgrades, ownership transfers, pauses, role changes, and implementation-registry updates.
- Alert on code appearance: Notify immediately when runtime bytecode is deployed.
- Match deployment recipe: Confirm the deploying factory, salt, initialization code, and resulting address.
- Verify runtime code: Compare deployed bytecode with the reviewed expectation.
- Inspect same-block activity: Check initialization, token transfers, approval use, and administrative calls.
- Monitor later upgrades: A deterministic proxy address may change implementation after deployment.
Common misconceptions about CREATE2
A deterministic address means the code is already fixed and safe
The address commits to initialization-code bytes under a specific factory and salt. Safety still depends on what that code does, deployment-time state, proxy behavior, external dependencies, permissions, and later upgrades.
An empty address cannot drain tokens
An empty address cannot execute contract code at that moment. It can still hold an allowance. If code is later deployed there, the address may use that authority.
The salt uniquely identifies the deployment
The salt is only one input. The factory address and initialization-code hash are equally important. Reusing a salt with different code can produce a different address.
Knowing the predicted address proves the factory will deploy it
Deployment can fail, be delayed, be blocked by existing account state, or never occur. Predictability does not guarantee execution.
CREATE2 lets anyone overwrite an existing contract
Contract-creation collision rules prevent deployment over an address with blocking code or nonce state. CREATE2 is not a general overwrite mechanism.
Selfdestruct always makes deterministic redeployment possible
Modern Ethereum rules generally preserve the code and storage of long-lived contracts after SELFDESTRUCT, preventing traditional multi-transaction delete-and-redeploy patterns.
A known factory guarantees every deployment is trustworthy
General factories may accept arbitrary initialization code. Each deployment recipe requires separate review.
A verified future contract source proves the prediction
Reviewers must reproduce the initialization-code hash and address calculation. Source code that is not connected to the exact factory, salt, constructor values, and creation bytecode does not prove what will appear.
Related TokenToolHub research
CREATE2 risk connects to source verification, token approvals, signature safety, hidden administrative paths, and historical selfdestruct behavior. Use the following resources to investigate each layer.
Hidden backdoors
Use the hidden backdoors guide to investigate upgrade, arbitrary-call, registry, ownership, and asset-sweep controls.
Smart contract verification
Read the smart contract verification guide to match source with deployed bytecode and review creation inputs.
Token Safety Checker
Use the Token Safety Checker to begin a structured token and permission review.
Crypto approval risks
Read the crypto approval risks guide before granting an unknown or undeployed spender token access.
Signature replay attacks
Use the signature replay attacks guide to evaluate domain, chain, nonce, deadline, and reuse protections.
Selfdestruct behavior
Read the selfdestruct smart contract guide to understand historical metamorphic patterns and modern redeployment limits.
Builder guidelines for safer deterministic deployment
Builders should make CREATE2 deployments independently reproducible. Users should not need to trust a front end to know what address will be deployed or who will control it.
Safer CREATE2 design principles
- Publish the complete recipe: Factory address, salt derivation, creation bytecode, constructor values, and expected address should be available.
- Bind ownership explicitly: Encode the intended owner or authenticated configuration into committed deployment data.
- Namespace user salts: Prevent unintended collisions or cross-user interference where appropriate.
- Emit clear deployment events: Include the created address, salt, owner, and configuration identifiers.
- Verify factory source: Users need to know how the factory transforms inputs and performs deployment.
- Limit factory upgrade power: If upgradeable, disclose governance, timelocks, and emergency authority.
- Avoid hidden external dependencies: Constructor behavior should not rely on unexplained mutable state.
- Validate initialization: Prevent uninitialized proxies, duplicate initialization, and wrong-owner deployment.
- Design safe public deployment: Front-running should not let the first caller gain control.
- Provide funding recovery evidence: Counterfactual accounts should have a tested path for accessing prefunded assets.
- Warn against premature approvals: Users should not grant broad permissions before code and ownership are verifiable.
- Monitor predeployment authority: Alert when predicted addresses accumulate balances or approvals.
- Document network assumptions: Deployment and selfdestruct behavior may differ across chains.
- Verify runtime after deployment: Address prediction is the beginning of verification, not the end.
Conclusion: deterministic addresses require predeployment security review
CREATE2 gives smart contract systems a powerful capability: an address can be known before the corresponding runtime code exists. This supports counterfactual wallets, deterministic factories, predictable escrows, protocol components, and account-abstraction workflows.
The same capability creates a predeployment risk stage. An address can receive funds, approvals, permit authority, operator permissions, protocol roles, and user trust before its behavior is visible on-chain. A code-free address may later become executable code without changing the address that users previously approved or funded.
The correct review method is to reconstruct the complete deployment recipe. Verify the factory, salt, initialization code, constructor arguments, ownership configuration, external dependencies, proxy architecture, deployment access, and final runtime bytecode. Then check which permissions and balances already belong to the predicted address.
Users should never treat code absence as proof of safety. Approval amount, spender identity, application origin, signature domain, deployment factory, and future control are more important than whether a block explorer currently shows an empty code field.
Your next action is to inspect the application through the smart contract verification workflow, review any spender permission through the approval risk framework, and use the Token Safety Checker as an initial layer before granting access to valuable assets.
Verify what the address can become, not only what it is now
Before funding, approving, signing for, or integrating a predicted address, reproduce the CREATE2 calculation and review the future contract's ownership, runtime behavior, upgrade controls, recovery path, and deployment authority.
FAQs
What is CREATE2 in a smart contract?
CREATE2 is an EVM contract-creation opcode that calculates the future contract address from the deploying contract, a 32-byte salt, and the hash of the complete initialization code.
How is CREATE2 different from CREATE?
CREATE normally derives the new address from the deployer's address and nonce. CREATE2 uses the deployer, salt, and initialization-code hash, allowing the address to be predicted before deployment.
What is a deterministic contract address?
A deterministic contract address is an address that can be reproduced from known deployment inputs instead of depending only on an unpredictable future transaction sequence.
Can an undeployed CREATE2 address receive ETH?
Yes. ETH can be sent to the address before code is deployed. Accessing it later depends on successfully deploying suitable contract code at that exact address.
Can an undeployed address receive token approvals?
Yes. Many token contracts allow users to approve any address as a spender, even when that address currently contains no code.
How can CREATE2 be involved in wallet drain scams?
A scam may ask a user to approve a predicted address while it is empty. Malicious code can later be deployed at that same address and attempt to use the pre-existing allowance.
Does an empty contract address mean it is safe?
No. The address may be a predicted CREATE2 destination that can receive code later. Users should review the permission request and deployment path rather than relying on current code absence.
Does CREATE2 guarantee the deployed contract is immutable?
No. The deployed contract may be a proxy, use delegatecall, read a mutable registry, depend on upgradeable contracts, or grant administrators broad control.
Do constructor arguments affect the CREATE2 address?
Yes. Constructor arguments are normally encoded into the initialization code, so changing them changes the initialization-code hash and predicted address.
Can two deployments use the same salt?
Yes. The same salt can produce different addresses when the deployer or initialization code differs. The address calculation depends on all three inputs.
Can another user front-run a CREATE2 deployment?
A public factory may allow another account to submit the same deployment recipe first. Whether this creates harm depends on whether ownership and initialization are securely bound to the intended user.
Can CREATE2 overwrite an existing contract?
No. Contract creation fails when the destination has blocking code or nonce state. CREATE2 is not a general mechanism for overwriting active contracts.
Can selfdestruct allow redeployment at the same CREATE2 address?
Traditional multi-transaction redeployment patterns are significantly limited on modern Ethereum because long-lived contracts generally retain code and storage after SELFDESTRUCT. Other networks may follow different rules.
What should I verify before funding a counterfactual wallet?
Verify the factory, salt, initialization code, constructor arguments, predicted address, owner configuration, deployment permissions, runtime code, upgrade controls, and recovery path.
References and further learning
Use primary protocol documentation when reviewing deterministic address calculations, contract-creation collisions, Solidity deployment behavior, selfdestruct changes, and counterfactual account patterns.
- EIP-1014: Skinny CREATE2
- EIP-684: Contract Creation Collision Rules
- EIP-6780: SELFDESTRUCT Only in the Same Transaction
- ERC-4337: Account Abstraction Using an Alternative Mempool
- Solidity Documentation: Salted Contract Creations with CREATE2
- Solidity Documentation: Inline Assembly and CREATE2
- OpenZeppelin Contracts: Create2 Utilities
- TokenToolHub: Hidden Backdoors in Smart Contracts
- TokenToolHub: Smart Contract Verification
- TokenToolHub: Token Safety Checker
- TokenToolHub: Crypto Approval Risks
- TokenToolHub: Signature Replay Attacks
- TokenToolHub: Selfdestruct in Smart Contracts
This TokenToolHub guide is educational research only. It is not investment advice, trading advice, legal advice, tax advice, cybersecurity advice, or an audit. Always verify the factory, salt, initialization code, constructor arguments, predicted address, deployment permissions, owner configuration, runtime bytecode, proxy architecture, approvals, signatures, network rules, and asset-recovery path before funding or authorizing a deterministic contract address.