Documentation
What we migrate
ChainClone creates a complete, deployable copy of any EVM smart contract from any supported source chain. Here is exactly what is included:
Bytecode
We extract the deployed bytecode from the source chain using eth_getCode. This is the compiled, binary representation of the contract logic. The copy is bit-for-bit identical to the original — same function selectors, same opcodes, same ABI.
Storage state
Smart contract storage is a key-value store of 32-byte slots. We enumerate all non-zero storage slots using a combination of strategies (see Storage enumeration) and include all discovered values in the migration output. This preserves balances, ownership mappings, counters, and any other state variables.
Native balance
If the contract holds native currency (ETH, BNB, MATIC, etc.), we record the balance and include the same amount in the migration output. Note: for paid on-chain deployments, we pre-fund the destination contract with the equivalent amount; you are responsible for ensuring the funding is correct.
Constructor arguments
We infer constructor arguments from the deployment transaction on the source chain (where available from block explorers or verified source). These are used to produce a clean redeployment on the destination chain.
Proxy and implementation pairs
Upgradeable proxy contracts (EIP-1967, OpenZeppelin Transparent Proxy, UUPS, Beacon Proxy) are detected automatically. Both the proxy and its current implementation are included in the migration output, with proper initialization data.
Token balances (ERC-20, ERC-721, ERC-1155)
For token contracts, we enumerate the full balance mapping from storage slots. This means all holder balances are preserved in the cloned contract. See Token balances for details and limitations.
What we don't migrate
Some data is structurally impossible or deliberately excluded from migration:
- Transaction history — past transactions are recorded on the source chain's ledger, not in the contract itself. The cloned contract starts with zero transaction history.
- Event logs — events are emitted during transactions and stored in block receipts, not in contract storage. They are not part of the contract state.
- External contract references — if the contract stores addresses of other contracts (e.g.,
address public owner = 0xABC...), those stored addresses still point to the source chain. You must update them manually after migration. - Off-chain data and oracles — any data that the contract reads from external sources (Chainlink feeds, IPFS CIDs, etc.) must be reconfigured for the destination chain.
- Bridge positions — tokens or assets locked in cross-chain bridges are not migrated.
- Gas price history — not part of contract state.
Storage enumeration
Enumerating all storage slots in a deployed contract is a non-trivial problem — EVM contracts can theoretically use any of 2256 possible storage slots. We use several complementary strategies:
Strategy 1: Verified source code analysis
If the contract is verified on a block explorer (Etherscan, Basescan, etc.), we parse the source code to determine the storage layout — exactly which slots correspond to which variables. This is the most accurate method.
Strategy 2: Sequential scan
We scan slots 0 through N (default: first 1,000 slots) using eth_getStorageAt. This catches all simple state variables, arrays (at their base slots), and fixed-size mappings.
Strategy 3: Event-driven slot discovery
We replay relevant events (Transfer, Approval, Deposit, etc.) from the contract's history to discover mapping keys. For ERC-20 contracts, for example, every Transfer event reveals a holder's address, which we use to compute the corresponding storage slot.
Strategy 4: Known slot patterns
ERC-20 balance mappings are always stored at keccak256(address . slot). ERC-721 owners at keccak256(tokenId . slot). We recognize these patterns for all major token standards and enumerate them directly.
Proxy contracts
We detect the following proxy patterns automatically:
- EIP-1967 Transparent Proxy — implementation slot at
0x360894... - EIP-1967 Beacon Proxy — beacon slot at
0xa3f0ad74... - UUPS (Universal Upgradeable Proxy Standard)
- OpenZeppelin TransparentUpgradeableProxy
- Gnosis Safe Proxy
- Minimal proxy (EIP-1167 clones)
For each proxy, both the proxy contract and its current implementation are included in the migration. The proxy's storage (including the stored implementation address) is updated to point to the new implementation address on the destination chain.
Token balances
Token balance migration works differently depending on the standard:
ERC-20
Balance storage is at keccak256(abi.encode(holder_address, balanceOf_slot)). We enumerate all holders from Transfer events and reconstruct the full balance mapping. Total supply is preserved.
ERC-721
Token ownership is stored at keccak256(abi.encode(tokenId, owners_slot)). We enumerate all token IDs from Transfer events. The balanceOf mapping is reconstructed from ownership data.
ERC-1155
The multi-token balance mapping is at keccak256(abi.encode(tokenId, keccak256(abi.encode(holder, balances_slot)))). We enumerate from TransferSingle and TransferBatch events.
Supported chains
The following chains are supported as source chains (we can read contracts from these):
| Chain | Chain ID | RPC source |
|---|---|---|
| Ethereum Mainnet | 1 | Public RPCs + ChainRPC |
| Base | 8453 | Public RPCs + ChainRPC |
| Arbitrum One | 42161 | Public RPCs + ChainRPC |
| Optimism | 10 | Public RPCs + ChainRPC |
| Polygon | 137 | Public RPCs + ChainRPC |
| BNB Chain | 56 | Public RPCs + ChainRPC |
| Avalanche C-Chain | 43114 | Public RPCs + ChainRPC |
| Custom RPC | Any EVM | Your endpoint |
Destination chains (we can deploy to these):
| Destination | Price per contract | Notes |
|---|---|---|
| L2aaS (your own chain) | Free | Import as genesis allocation or live deployment |
| Export ZIP | $47.50 USDC | Deploy anywhere yourself |
| Base / Arbitrum / Optimism / Polygon | $97.53 USDC | We deploy on-chain for you |
| BNB Chain | $31.17 USDC | We deploy on-chain for you |
| Ethereum L1 | $478.21 USDC | Includes mainnet gas budget |
Pricing
Pricing is per contract. Volume discounts apply automatically to all contracts in a single order:
| Order size | Discount |
|---|---|
| 1–4 contracts | No discount |
| 5–9 contracts | 5% off |
| 10–19 contracts | 10% off |
| 20–49 contracts | 20% off |
| 50–99 contracts | 30% off |
| 100+ contracts | 40% off |
Payment is in USDC or USDT via your wallet. Payment is verified on-chain before migration begins.
Refund policy
Our refund policy:
- Migration not started: 100% refund if we haven't submitted any on-chain transaction yet.
- Migration failed after gas spent: Full refund minus the value of gas already consumed on the destination chain. We provide a detailed breakdown.
- Bad input from customer: No refund for invalid addresses, incompatible contract code, or source chains that become unavailable after payment.
- Partial completion: Refund for undeployed contracts only. Contracts already deployed are considered delivered.
To request a refund, use the job URL from your results page. Refunds are processed within 48 hours to the same wallet that paid.
Free sample download
Before paying, you can download a free sample for the first contract in your order. The sample ZIP contains:
bytecode.hex— the raw deployed bytecodeabi.json— the contract ABI (if available from verified source)storage-layout.json— detected slot layout and variable typesanalysis.txt— summary: contract type, storage slots found, dependencies
The sample does not include the full storage state dump (that requires payment). It is enough to verify that we correctly identified the contract and its structure, but not enough to deploy a functional clone on your own.
Known limitations
- Very large contracts (>24 KB bytecode): EVM has a 24 KB bytecode size limit. Contracts near this limit may require special handling. We will flag these during analysis.
- Diamond proxies (EIP-2535): Complex multi-facet diamonds are detected but may require manual verification of facet addresses after migration.
- Self-destructed contracts: Contracts that have been self-destructed on the source chain cannot be cloned — the bytecode no longer exists.
- Cross-chain dependencies: Contracts that call other contracts by hardcoded address will still reference the source chain's addresses. You must update these manually.
- Custom revert strings and error data: Preserved in bytecode exactly — no changes needed.
- Immutable variables (Solidity immutables): Baked into the bytecode at deployment time — preserved exactly in the clone.
- Storage gaps: We only copy non-zero storage slots. Zero-value slots are the default and are not stored on the destination chain (they are equal to the default anyway).
Ready to migrate?
Start a migration →