Bird
Raised Fist0
Blockchain / Solidityprogramming~15 mins

Minimal proxy (clone) pattern in Blockchain / Solidity - Deep Dive

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Overview - Minimal proxy (clone) pattern
What is it?
The minimal proxy (clone) pattern is a way to create many lightweight copies of a smart contract on a blockchain. Instead of copying all the code, these clones share the logic from a single original contract but have their own separate storage. This saves space and gas costs when deploying multiple similar contracts. Each clone acts like an independent contract but relies on the original for its behavior.
Why it matters
Deploying full copies of smart contracts for every instance can be very expensive and slow on blockchains. The minimal proxy pattern solves this by creating tiny contracts that delegate calls to a master contract, drastically reducing deployment costs. Without this, developers would face high fees and slower innovation when scaling decentralized applications.
Where it fits
Before learning this, you should understand basic smart contract development and how contract calls work on blockchains. After mastering minimal proxies, you can explore advanced upgradeability patterns and gas optimization techniques in decentralized applications.
Mental Model
Core Idea
A minimal proxy is a tiny contract that forwards all calls to a master contract, sharing its logic but keeping separate data.
Think of it like...
It's like having many identical remote controls that don't have their own electronics but send signals to one main device to perform actions.
┌───────────────┐       ┌─────────────────────┐
│ Minimal Proxy │──────▶│ Master Contract Code │
│ (tiny clone)  │       │ (shared logic only)  │
└──────┬────────┘       └─────────┬───────────┘
       │                          │
       │ Separate Storage         │
       ▼                          ▼
  ┌───────────────┐          ┌───────────────┐
  │ Proxy Storage │          │ Master Storage│
  │ (unique data) │          │ (logic only)  │
  └───────────────┘          └───────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Smart Contracts Basics
🤔
Concept: Learn what smart contracts are and how they run on blockchains.
Smart contracts are programs stored on a blockchain that run exactly as programmed. They hold data and code, and users interact with them by sending transactions. Each contract has its own address and storage.
Result
You know that smart contracts combine code and data on the blockchain and can be called by users or other contracts.
Understanding that contracts combine code and storage is key to grasping why cloning just the code can save resources.
2
FoundationHow Contract Calls and Storage Work
🤔
Concept: Learn how one contract can call another and how storage is separate per contract.
When a contract calls another, it can execute the called contract's code but the storage used depends on the contract's own address. Each contract has isolated storage, so code reuse doesn't mean shared data.
Result
You understand that code can be shared but storage remains unique per contract.
Knowing that storage is tied to the contract address helps explain how minimal proxies keep separate data while sharing logic.
3
IntermediateWhat Is a Minimal Proxy Contract
🤔
Concept: Introduce the minimal proxy as a tiny contract forwarding calls to a master contract.
A minimal proxy contract contains very little code: just enough to forward any call it receives to a master contract using a special instruction called DELEGATECALL. This means the master contract's code runs but uses the proxy's storage.
Result
You see how minimal proxies act as lightweight clones that share logic but keep their own data.
Understanding DELEGATECALL is crucial because it lets one contract run another's code in its own storage context.
4
IntermediateBenefits of Using Minimal Proxies
🤔Before reading on: do you think minimal proxies save deployment cost by copying less code or by sharing storage? Commit to your answer.
Concept: Explain how minimal proxies reduce gas costs and improve scalability.
Deploying a full contract each time costs a lot of gas because all code is stored on-chain. Minimal proxies only deploy a small forwarding contract, saving space and gas. Each proxy has its own storage, so they behave independently but share the same logic.
Result
You understand that minimal proxies save money and allow many contract instances without duplicating code.
Knowing that proxies share code but not storage explains why they are both cheap and flexible.
5
IntermediateHow to Deploy a Minimal Proxy
🤔Before reading on: do you think deploying a minimal proxy requires writing full contract code or just a small bytecode snippet? Commit to your answer.
Concept: Learn the practical steps to create a minimal proxy using standard bytecode templates.
Minimal proxies use a fixed bytecode pattern that includes the address of the master contract. Deployment involves inserting the master contract's address into this template and deploying the small contract. Tools like OpenZeppelin's Clones library automate this.
Result
You can deploy minimal proxies efficiently by using standard templates and libraries.
Understanding the bytecode template helps you see how minimal proxies are standardized and easy to create.
6
AdvancedSecurity Considerations with Minimal Proxies
🤔Before reading on: do you think minimal proxies have their own code vulnerabilities or inherit all from the master contract? Commit to your answer.
Concept: Explore how security depends on the master contract and what risks proxies introduce.
Since minimal proxies delegate calls to the master contract, any bug in the master affects all proxies. Proxies themselves have minimal code, so their risk is low, but storage collisions or incorrect initialization can cause issues. Proper initialization and upgrade patterns are important.
Result
You know that securing the master contract is critical and proxies must be carefully initialized.
Recognizing that proxies share logic means a single bug can impact many clones, emphasizing careful master contract design.
7
ExpertAdvanced Internals of DELEGATECALL in Proxies
🤔Before reading on: do you think DELEGATECALL changes the caller's address or storage context? Commit to your answer.
Concept: Deep dive into how DELEGATECALL works at the Ethereum Virtual Machine level for proxies.
DELEGATECALL executes code from another contract but keeps the original caller and the storage of the calling contract. This means the proxy's storage is used, but the code runs as if it were the master contract. This subtlety allows proxies to behave like clones but requires careful handling of msg.sender and storage layout.
Result
You understand the exact behavior of DELEGATECALL that enables minimal proxies to work.
Knowing DELEGATECALL's behavior explains why proxies can share code but maintain separate state and why storage layout compatibility is vital.
Under the Hood
Minimal proxies use the EVM instruction DELEGATECALL to forward any function call to a master contract. When a call arrives at the proxy, it executes the master contract's code but uses the proxy's own storage and context. The proxy's bytecode is a small fixed pattern that includes the master contract's address. This pattern is very compact, reducing deployment cost. The proxy does not store any logic itself, only the address to delegate to. Calls, return data, and errors are forwarded transparently.
Why designed this way?
The pattern was designed to save gas and storage on blockchains where deploying full contracts is expensive. Instead of copying code multiple times, developers reuse a single implementation. Alternatives like full contract cloning or inheritance were too costly or inflexible. The minimal proxy pattern balances efficiency with flexibility by leveraging DELEGATECALL, a powerful EVM feature introduced early in Ethereum's design.
┌───────────────┐
│ User or Other │
│ Contract Call │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Minimal Proxy │
│ (tiny bytecode│
│  with address │
│  of master)   │
└──────┬────────┘
       │ DELEGATECALL
       ▼
┌───────────────┐
│ Master Contract│
│ (full logic)   │
└───────────────┘

Storage used: Proxy's own storage
Code executed: Master's code
Context: Proxy's context (msg.sender, storage)
Myth Busters - 4 Common Misconceptions
Quick: Do minimal proxies share storage with the master contract? Commit to yes or no.
Common Belief:Minimal proxies share both code and storage with the master contract.
Tap to reveal reality
Reality:Minimal proxies share only the code (logic) but each proxy has its own separate storage.
Why it matters:Believing storage is shared can lead to dangerous assumptions about data isolation, causing bugs or security issues.
Quick: Do minimal proxies have the full code of the master contract inside them? Commit to yes or no.
Common Belief:Each minimal proxy contains a full copy of the master contract's code.
Tap to reveal reality
Reality:Minimal proxies contain only a small forwarding bytecode that delegates calls to the master contract; they do not duplicate the full code.
Why it matters:Thinking proxies duplicate code leads to misunderstanding gas costs and deployment efficiency.
Quick: Can a bug fixed in the master contract automatically fix all deployed proxies? Commit to yes or no.
Common Belief:Fixing the master contract code automatically fixes all proxies without redeployment.
Tap to reveal reality
Reality:Since proxies delegate to the master contract's address, fixing the master contract fixes all proxies only if the master contract is upgradeable or replaced; otherwise, proxies point to the original immutable master.
Why it matters:Assuming automatic fixes can cause overconfidence and neglect of upgrade or migration strategies.
Quick: Does DELEGATECALL change the caller's address (msg.sender)? Commit to yes or no.
Common Belief:DELEGATECALL changes msg.sender to the master contract's address.
Tap to reveal reality
Reality:DELEGATECALL preserves the original caller's address (msg.sender) as seen by the master contract code.
Why it matters:Misunderstanding this can cause incorrect access control or logic errors in proxy-based contracts.
Expert Zone
1
Minimal proxies require the master contract's storage layout to remain compatible with the proxies to avoid corrupting data.
2
Initialization of proxies must be done carefully because constructors do not run on proxies; instead, an initializer function is used.
3
Gas savings from minimal proxies are significant but come with complexity in debugging and tracing transactions.
When NOT to use
Minimal proxies are not suitable when contracts require unique code logic per instance or when upgradeability patterns demand more complex state management. Alternatives include full contract deployment or using proxy patterns with upgradeable logic like Transparent or UUPS proxies.
Production Patterns
In production, minimal proxies are widely used for deploying many instances of token contracts, NFT collections, or decentralized finance pools efficiently. They are often combined with factory contracts that automate deployment and initialization, and with upgradeable master contracts to allow bug fixes.
Connections
Factory Pattern
Builds-on
Minimal proxies are often deployed by factory contracts that automate creating many clones, showing how design patterns combine for scalable contract deployment.
Software Design Patterns - Proxy Pattern
Same pattern
The minimal proxy pattern in blockchain is a specialized form of the proxy design pattern in software engineering, where a lightweight object controls access to a heavier one.
Remote Controls in Electronics
Analogy in different field
Just like minimal proxies delegate commands to a master contract, remote controls send signals to a main device, illustrating delegation and separation of control and execution.
Common Pitfalls
#1Incorrectly assuming the proxy runs its own constructor code.
Wrong approach:contract Proxy { constructor() { // initialization code here } // delegate calls }
Correct approach:contract Proxy { function initialize() external { // initialization logic called after deployment } // delegate calls }
Root cause:Constructors do not run on minimal proxies because they only contain forwarding bytecode; initialization must be done via external functions.
#2Using incompatible storage layouts between master and proxies.
Wrong approach:Master contract changes storage variables order or types after proxies are deployed.
Correct approach:Maintain consistent storage layout in master contract to match proxies' expectations.
Root cause:DELEGATECALL uses proxy storage, so mismatched layouts cause data corruption.
#3Deploying proxies without setting the correct master contract address in bytecode.
Wrong approach:Deploying proxy bytecode with a wrong or zero address for the master contract.
Correct approach:Insert the correct master contract address into the proxy bytecode template before deployment.
Root cause:The proxy must know where to delegate calls; incorrect address breaks functionality.
Key Takeaways
Minimal proxies are tiny contracts that forward calls to a master contract, sharing logic but keeping separate storage.
They save gas and deployment costs by avoiding code duplication on the blockchain.
DELEGATECALL is the key EVM instruction enabling proxies to run master code in their own storage context.
Proper initialization and storage layout compatibility are critical to avoid bugs and security issues.
Minimal proxies are widely used in production to efficiently deploy many contract instances with shared logic.

Practice

(1/5)
1. What is the main purpose of the Minimal proxy (clone) pattern in blockchain development?
easy
A. To replace the original contract with a new one
B. To increase the size of deployed contracts
C. To create cheap copies of contracts by forwarding calls
D. To store large amounts of data on-chain

Solution

  1. Step 1: Understand the pattern's goal

    The minimal proxy pattern is designed to save gas and storage by creating lightweight copies of a contract.
  2. Step 2: Identify the correct purpose

    It achieves this by forwarding calls to the original contract instead of duplicating all code.
  3. Final Answer:

    To create cheap copies of contracts by forwarding calls -> Option C
  4. Quick Check:

    Minimal proxy pattern = cheap contract copies [OK]
Hint: Minimal proxy means cheap clones forwarding calls [OK]
Common Mistakes:
  • Thinking it increases contract size
  • Confusing it with data storage methods
  • Assuming it replaces original contracts
2. Which of the following Solidity code snippets correctly declares a minimal proxy clone using the create opcode?
easy
A. address clone = create(0, bytecode, bytecode.length);
B. address clone = new Contract();
C. address clone = create2(0, bytecode, bytecode.length);
D. address clone = delegatecall(bytecode);

Solution

  1. Step 1: Identify the correct opcode for minimal proxy creation

    The create opcode is used to deploy a new contract with given bytecode.
  2. Step 2: Match the syntax

    The syntax create(0, bytecode, bytecode.length) correctly uses create with zero value and bytecode parameters.
  3. Final Answer:

    address clone = create(0, bytecode, bytecode.length); -> Option A
  4. Quick Check:

    Minimal proxy uses create opcode like address clone = create(0, bytecode, bytecode.length); [OK]
Hint: Minimal proxy uses create, not new or delegatecall [OK]
Common Mistakes:
  • Using new keyword which deploys full contract
  • Confusing create2 with create
  • Using delegatecall which does not deploy
3. Given the following Solidity code snippet for deploying a minimal proxy clone, what will be the output of clone.owner() if the original contract's owner is set to address 0x1234...?
address clone = Clones.clone(original);
// original.owner() returns 0x1234...
// clone forwards calls to original
medium
A. 0x1234... (same owner as original)
B. 0x0000... (zero address)
C. Revert error due to missing owner variable
D. Address of the clone contract

Solution

  1. Step 1: Understand call forwarding in minimal proxy

    The clone forwards calls to the original contract, but storage is separate, so state variables like owner are not shared.
  2. Step 2: Determine owner value returned

    Since owner() reads from the clone's storage which is uninitialized, it returns 0x0000... (zero address).
  3. Final Answer:

    0x0000... (zero address) -> Option B
  4. Quick Check:

    Clone forwards calls but has separate storage, owner = zero address [OK]
Hint: Clone has separate storage, owner defaults to zero [OK]
Common Mistakes:
  • Assuming clone shares storage with original
  • Expecting original owner to be returned
  • Thinking clone address is returned
4. Identify the error in this minimal proxy deployment code snippet:
function clone(address implementation) external returns (address instance) {
    bytes20 targetBytes = bytes20(implementation);
    assembly {
        let clone_code := mload(0x40)
        mstore(clone_code, 0x3d602d80600a3d3981f3)
        mstore(add(clone_code, 0x14), targetBytes)
        instance := create(0, clone_code, 0x37)
    }
    require(instance != address(0), "Create failed");
}
medium
A. No error, code is correct
B. Missing delegatecall opcode in assembly
C. Using bytes20 instead of bytes32 for target address
D. Incorrect length passed to create (0x37 instead of 0x2d)

Solution

  1. Step 1: Check the length parameter for create

    The minimal proxy bytecode length is typically 0x2d (45 bytes), but 0x37 (55 bytes) is passed incorrectly.
  2. Step 2: Understand impact of wrong length

    Passing wrong length causes deployment of invalid bytecode, leading to failure or unexpected behavior.
  3. Final Answer:

    Incorrect length passed to create (0x37 instead of 0x2d) -> Option D
  4. Quick Check:

    Create length must match bytecode size [OK]
Hint: Check create length matches bytecode size [OK]
Common Mistakes:
  • Ignoring bytecode length mismatch
  • Confusing bytes20 and bytes32 usage
  • Assuming delegatecall needed in deployment
5. You want to deploy 1000 instances of a contract cheaply using the minimal proxy pattern. Which approach best reduces gas and storage costs while allowing each clone to have its own owner?
hard
A. Use minimal proxies forwarding to one implementation and store owner in each clone's storage
B. Deploy 1000 full contracts separately with unique owners
C. Use minimal proxies forwarding to one implementation and store owner in the implementation contract
D. Deploy one contract and share the same owner for all clones

Solution

  1. Step 1: Understand minimal proxy benefits

    Minimal proxies save gas by sharing code but have separate storage for each clone.
  2. Step 2: Assign unique owners per clone

    Storing owner in each clone's storage allows unique ownership while sharing logic.
  3. Step 3: Evaluate options

    Use minimal proxies forwarding to one implementation and store owner in each clone's storage uses minimal proxies with per-clone storage, reducing gas and allowing unique owners.
  4. Final Answer:

    Use minimal proxies forwarding to one implementation and store owner in each clone's storage -> Option A
  5. Quick Check:

    Minimal proxy + per-clone storage = cheap unique owners [OK]
Hint: Store owner in clone storage, share code via proxy [OK]
Common Mistakes:
  • Storing owner only in implementation (shared state)
  • Deploying full contracts wastes gas
  • Sharing one owner for all clones