Skip to content

Potential Risks

DISCLAIMER // NFA // DYOR

This analysis is based on a full disassembly of the deployed bytecode — the contract source code is not verified on Etherscan. The published upstream source was compiled locally and matches the on-chain creation bytecode byte for byte; that match was established by us, not by Etherscan. We are not smart contract security experts. This document should not be considered a comprehensive security audit or financial advice. Always verify critical information independently.

⊙ generated by robots | curated by humans

METADATA
Contract Address 0x4e59b448...B4956C (etherscan)
Network Ethereum Mainnet
Analysis Date 2026-10-30

Risk Summary

SEVERITY COUNT
Critical 0
High 0
Medium 2
Low 2
Informational 4

Every Medium and Low finding describes a way the contract can surprise the code or the person deploying through it; none puts assets held by this contract at risk.


Medium Risks

Constructor msg.sender Is the Factory

FIELD VALUE
Severity Medium
Category Trust Assumption

A contract deployed through this CREATE2 factory sees msg.sender == 0x4e59b448...B4956C (etherscan) inside its constructor, not the Externally Owned Account (EOA) that sent the transaction. A local fork test confirmed it: init code that stored CALLER into slot 0 recorded the factory's address.

Any constructor that grants a role to msg.sender therefore grants it to the factory. The pattern Ownable(msg.sender), or an AccessControl constructor calling _grantRole(DEFAULT_ADMIN_ROLE, msg.sender), makes this contract the owner or admin. This contract has no code path that can call anything except CREATE2, so that role can never be exercised or transferred. The deployed contract is locked out of every function gated on it.

Mitigation sits with the deployer: pass the intended owner as a constructor argument encoded into the init code, and check the owner on the deployed contract before relying on it.

Deployments Can Be Copied by Anyone

FIELD VALUE
Severity Medium
Category Trust Assumption

The factory does not check its caller, and the deployment address does not depend on the caller. A pending deployment in the public Mempool can be copied verbatim and submitted by someone else with a higher fee. Because the address depends only on salt and init code, the copy produces the same contract at the same address. The original transaction then reverts on the occupied address.

For a constructor that reads only its init code, this changes nothing but who paid the gas. It matters when the constructor depends on something other than its init code:

  • tx.origin. The fork test recorded the submitting EOA as tx.origin in the constructor. A contract that makes tx.origin its owner hands ownership to whoever lands the transaction first.
  • msg.value. The copier chooses how much ETH to forward, and the init code cannot require a particular amount unless the constructor checks it.
  • Block-dependent values such as block.timestamp or external contract state read during construction.

A deployer who needs the constructor to bind to a specific party should encode that party into the init code, or deploy from a factory that mixes the caller into the salt.


Low Risks

Failures Are Indistinguishable

FIELD VALUE
Severity Low
Category Complexity

The runtime ends a failed CREATE2 with revert(0, 0). A constructor that reverted with a reason string, a constructor that ran out of gas, runtime code above the 24,576-byte EIP-170 limit, and a salt and init code pair that has already been deployed (an occupied address) all surface as the same empty revert. The full list is in the Failure Cases table. Debugging a failed deployment requires a trace of the inner creation frame.

Calldata shorter than 32 bytes and init code longer than 49,152 bytes (EIP-3860) fail differently: both halt exceptionally and consume all forwarded gas. Both were reproduced on a fork.

Return Value Is Not ABI-Encoded

FIELD VALUE
Severity Low
Category Complexity

The factory returns the deployed address as 20 raw bytes. A Solidity caller that does abi.decode(ret, (address)) will revert, because Application Binary Interface (ABI) decoding expects a 32-byte word. Callers must read the bytes directly. A caller that expects a 32-byte word without checking the length may read past the end of the return data, depending on the language and version. Foundry and the upstream scripts handle the raw format; hand-written integrations are where this shows up.


Informational

Not a Proxy

FIELD VALUE
Severity Informational
Category Complexity

The upstream project names this a "deployment proxy". It never uses delegatecall and has no implementation contract. In the sense this site's Proxy Contract page uses the word, it is a factory. The name describes its role in the deployment flow: the factory, not the deployer, is the sender input to the CREATE2 address formula.

Cross-Chain Availability Depends on Pre-EIP-155 Transactions

FIELD VALUE
Severity Informational
Category External Dependency

The factory reaches a new chain only through its one pre-signed deployment transaction, which has a fixed gas price of 100 Gwei, a fixed 100,000 gas limit, and no EIP-155 chain id. A chain will not get the factory at this address if it rejects unprotected transactions, if its minimum gas price is above 100 gwei, or if its gas schedule makes the 68,131-gas deployment exceed 100,000. Some Ethereum clients refuse unprotected transactions over Remote Procedure Call (RPC) by default, which can make the transaction hard to submit even where consensus accepts it. On such a chain the keyless transaction cannot fill the address; only the chain's own genesis or state configuration could.

Of the eight chains in Cross-Chain Deployments, three did not receive the factory through the keyless transaction: MegaETH and Robinhood Chain never ran it, and on Arbitrum One it reverted against code already in place. Any chain not in that table should be checked with cast code before relying on the address.

Stranded ETH at the Keyless Signer

FIELD VALUE
Severity Informational
Category Economic

The signer 0x3fab1846...a45362 (etherscan) held ~0.025 ETH at block 26,306,072 (etherscan). Its nonce is 1, and its only known valid signature was the deployment. No private key for the signer is known to exist, and recovering one from a hand-chosen signature is computationally infeasible, so ETH sent beyond the 0.01 ETH the deployment uses cannot be recovered. The amount here is small.

Immutable, Ownerless Runtime

FIELD VALUE
Severity Informational
Category Centralization

Based on the bytecode, the runtime contains no SLOAD, SSTORE, CALLER, ORIGIN, DELEGATECALL, or SELFDESTRUCT opcode. No party can alter or remove it, and under Keyless Deployment no known key can place different code at this address by transaction; a chain that sets the address in its genesis state is outside that guarantee. The trust surface of using it is the Ethereum Virtual Machine's (EVM) CREATE2 semantics and the 69 bytes shown in Functions.