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
Minimal Proxy (Clone) Pattern in Solidity
📖 Scenario: You are building a smart contract system on Ethereum. You want to create many lightweight copies (clones) of a main contract to save gas and storage. This is useful when you have a standard contract logic but want separate instances for different users.
🎯 Goal: Build a minimal proxy contract that clones a main contract using the EIP-1167 minimal proxy pattern. You will create the main contract, then write a factory contract that deploys clones pointing to the main contract.
📋 What You'll Learn
Create a main contract called LogicContract with a public uint variable value and a function setValue(uint _value) to update it.
Create a factory contract called CloneFactory with a function createClone(address target) that deploys a minimal proxy clone of target using assembly.
Store the address of the deployed clone in a public variable lastClone.
Write a function getCloneValue() in the factory that calls value() on the last clone and returns it.
Print the address of the last clone and the value stored in it.
💡 Why This Matters
🌍 Real World
Minimal proxy clones save gas and storage on Ethereum by reusing contract logic. This pattern is widely used in DeFi and NFT projects to deploy many instances cheaply.
💼 Career
Understanding minimal proxies is important for blockchain developers working on scalable smart contract systems and optimizing gas costs.
Progress0 / 4 steps
1
Create the main contract with a value variable and setter
Create a contract called LogicContract with a public uint variable named value. Add a public function setValue(uint _value) that sets value to _value.
Blockchain / Solidity
Hint
Think of LogicContract as the main blueprint. It has a number value and a way to change it.
2
Add the clone factory contract with createClone function
Create a contract called CloneFactory. Inside it, declare a public address variable lastClone. Add a public function createClone(address target) that deploys a minimal proxy clone of target using assembly and stores the clone address in lastClone. Use the standard EIP-1167 bytecode pattern for the clone.
Blockchain / Solidity
Hint
Use assembly to write the minimal proxy bytecode. The pattern is fixed and uses the create opcode.
3
Add a function to get the value from the last clone
In the CloneFactory contract, add a public view function getCloneValue() that calls the value() function on the lastClone address using staticcall and returns the uint value.
Blockchain / Solidity
Hint
Use staticcall to safely call the value() function on the clone without changing state.
4
Print the last clone address and its stored value
Add a public view function printLastCloneInfo() in CloneFactory that returns the lastClone address and the uint value from getCloneValue(). Then write a simple script or test that deploys LogicContract, deploys CloneFactory, creates a clone of LogicContract, sets the value on the clone to 42, and prints the clone address and value.
Blockchain / Solidity
Hint
Return both the clone address and its stored value. The test script simulates deployment and interaction.
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
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.
Step 2: Identify the correct purpose
It achieves this by forwarding calls to the original contract instead of duplicating all code.
Final Answer:
To create cheap copies of contracts by forwarding calls -> Option C
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
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.
Step 2: Determine owner value returned
Since owner() reads from the clone's storage which is uninitialized, it returns 0x0000... (zero address).
Final Answer:
0x0000... (zero address) -> Option B
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:
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
Step 1: Understand minimal proxy benefits
Minimal proxies save gas by sharing code but have separate storage for each clone.
Step 2: Assign unique owners per clone
Storing owner in each clone's storage allows unique ownership while sharing logic.
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.
Final Answer:
Use minimal proxies forwarding to one implementation and store owner in each clone's storage -> Option A