# Transparent vs UUPS vs Beacon Proxy — कौन सा Pattern उपयोग करें
Smart contracts design से immutable हैं, लेकिन यह immutability एक problem बन जाती है जब आपको bug fix करना हो या features add करने हों। Proxy patterns एक elegant solution offer करते हैं: logic (upgradeable) को storage (permanent) से separate करना।
2026 में, तीन patterns dominate करते हैं: Transparent Proxy, UUPS (Universal Upgradeable Proxy Standard) और Beacon Proxy। प्रत्येक अपने distinct trade-offs के साथ।
Upgradeability की Problem
Proxies क्यों?
बिना proxy:
// V1: Initial deploy
contract Token {
mapping(address => uint256) public balances;
function transfer(address to, uint256 amount) external {
balances[msg.sender] -= amount;
balances[to] += amount;
}
}
// Bug discover हुआ: sufficient balance पर कोई check नहीं!
// → Data migration के साथ redeploy के बिना correct करना impossible
Proxy के साथ:
User → Proxy (storage) → Implementation (logic)
↓
(delegatecall)
Proxy implementation की code को proxy के context में (इसलिए proxy की storage के साथ) execute करने के लिए delegatecall का उपयोग करता है।
Transparent Proxy Pattern
Architecture
Transparent Proxy admin (जो upgrade कर सकता है) और users (जो contract use करते हैं) के बीच calls को strictly separate करता है।
Principle:
- अगर
msg.sender == admin→ proxy के admin functions execute
- नहीं तो → implementation को delegatecall
Diagram:
┌─────────────────────────────┐
│ TransparentProxy │
│ - admin: address │
│ - implementation: address │
│ - storage variables │
├─────────────────────────────┤
│ fallback() { │
│ if (msg.sender == admin)│
│ → admin functions │
│ else │
│ → delegatecall impl │
│ } │
└─────────────────────────────┘
↓ delegatecall
┌─────────────────────────────┐
│ Implementation V1 │
│ - business logic │
└─────────────────────────────┘
Code (OpenZeppelin):
// OpenZeppelin के साथ deployment
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
contract MyImplementation {
uint256 public value;
function initialize(uint256 _value) public {
value = _value;
}
function setValue(uint256 _value) public {
value = _value;
}
}
// Deploy script
ProxyAdmin admin = new ProxyAdmin();
MyImplementation impl = new MyImplementation();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(admin),
abi.encodeCall(impl.initialize, (42))
);
// Usage
MyImplementation proxied = MyImplementation(address(proxy));
proxied.setValue(100); // काम करता है
// Upgrade (ProxyAdmin से)
MyImplementationV2 implV2 = new MyImplementationV2();
admin.upgrade(proxy, address(implV2));
Strong Points
1. Admin/User Separation
User के लिए admin functions call करना impossible, selector collisions avoid करता है।
2. Proven Security
सबसे old और सबसे audited pattern। Major protocols द्वारा use किया गया (पहले Compound, MakerDAO)।
3. Separate ProxyAdmin
ProxyAdmin एक multisig या timelock हो सकता है, robust governance offer करता है।
Weak Points
1. Significant Gas Overhead
हर user call को msg.sender == admin verify करना होता है, जो per call ~2,600 gas extra cost करता है।
2. Complexity
तीन contracts deploy करने होते हैं: Implementation + Proxy + ProxyAdmin।
3. Possible Selector Collision
अगर implementation में proxy के admin function जैसा same selector वाला function है, user इसे कभी call नहीं कर पाएगा।
Gas Costs
| Operation | Gas |
|-----------|-----|
| Deploy Proxy | ~500,000 |
| Deploy ProxyAdmin | ~250,000 |
| Call function (user) | +2,600 gas overhead |
| Upgrade | ~30,000 |
UUPS Pattern (Universal Upgradeable Proxy Standard)
Architecture
UUPS logic को reverse करता है: upgradeTo function proxy में नहीं implementation में है। Proxy minimal है (सिर्फ fallback)।
Principle:
- Proxy = dumb forwarder (सिर्फ delegatecall)
- Implementation = upgrade logic contain करता है
Diagram:
┌─────────────────────────────┐
│ ERC1967Proxy (minimal) │
│ - implementation: address │
│ - storage variables │
├─────────────────────────────┤
│ fallback() { │
│ delegatecall(impl) │
│ } │
└─────────────────────────────┘
↓ delegatecall
┌─────────────────────────────┐
│ UUPSImplementation │
│ - business logic │
│ - upgradeTo(address) │ ← यहाँ upgrade logic
└─────────────────────────────┘
Code (OpenZeppelin):
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract MyImplementationUUPS is UUPSUpgradeable, OwnableUpgradeable {
uint256 public value;
function initialize(uint256 _value) public initializer {
__Ownable_init();
__UUPSUpgradeable_init();
value = _value;
}
function setValue(uint256 _value) public {
value = _value;
}
// CRITICAL: onlyOwner से upgradeTo protect करें
function _authorizeUpgrade(address newImplementation)
internal
override
onlyOwner
{}
}
// Deploy
MyImplementationUUPS impl = new MyImplementationUUPS();
ERC1967Proxy proxy = new ERC1967Proxy(
address(impl),
abi.encodeCall(impl.initialize, (42))
);
// Usage
MyImplementationUUPS proxied = MyImplementationUUPS(address(proxy));
// Upgrade (owner से)
MyImplementationUUPSV2 implV2 = new MyImplementationUUPSV2();
proxied.upgradeTo(address(implV2));
Strong Points
1. Gas Optimized
Proxy में कोई admin check नहीं, per call ~2,600 gas save करता है।
2. Minimal Proxy
एक single lightweight proxy contract (ERC1967Proxy ~50 lines)।
3. Flexibility
Implementation द्वारा upgrade logic customize किया जा सकता है (timelocks, voting, etc.)।
Weak Points
1. Critical Error Risk
अगर आप upgradeTo function के बिना या गलत तरीके से protected implementation deploy करते हैं, contract permanently non-upgradeable हो जाता है।
2. Devs के लिए Complexity
हर नई implementation को UUPSUpgradeable inherit करना और _authorizeUpgrade implement करना MUST।
3. Implementation में Attack Surface
_authorizeUpgrade में bug attacker को contract का control लेने allow कर सकता है।
Gas Costs
| Operation | Gas |
|-----------|-----|
| Deploy Proxy | ~200,000 |
| Call function (user) | Baseline (कोई overhead नहीं) |
| Upgrade | ~30,000 |
Savings: Transparent से deployment में ~60% सस्ता, per call ~10% सस्ता।
Beacon Proxy Pattern
Architecture
Beacon Proxy multiple proxies को एक single transaction में upgrade करने के लिए designed है। सभी proxies एक Beacon को point करते हैं जो implementation को point करता है।
Principle:
- Beacon = contract जो implementation का address store करता है
- Multiple proxies = सभी same Beacon को point करते हैं
- Upgrade = Beacon में implementation change (सभी proxies simultaneously upgrade)
Diagram:
Proxy1 ──┐
Proxy2 ──┼──→ Beacon → Implementation
Proxy3 ──┘
Upgrade:
admin.upgradeTo(newImpl) → Beacon.implementation = newImpl
→ सभी Proxies automatically newImpl use करते हैं
Code (OpenZeppelin):
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
contract MyImplementation {
uint256 public value;
function initialize(uint256 _value) public {
value = _value;
}
}
// Deploy
MyImplementation impl = new MyImplementation();
UpgradeableBeacon beacon = new UpgradeableBeacon(address(impl));
// Same Beacon को point करते 100 proxies deploy करें
for (uint i = 0; i < 100; i++) {
BeaconProxy proxy = new BeaconProxy(
address(beacon),
abi.encodeCall(impl.initialize, (i))
);
}
// एक transaction में सभी proxies UPGRADE
MyImplementationV2 implV2 = new MyImplementationV2();
beacon.upgradeTo(address(implV2));
Strong Points
1. Mass Upgrade
1000 contracts को एक single transaction में upgrade (1000 की बजाय)।
2. Gas Savings
अगर आपके पास N proxies हैं, upgrade cost fixed है (~30k gas) N × 30k की बजाय।
3. Coordination
Guarantee करता है कि सभी proxies implementation के same version use करते हैं।
Weak Points
1. EXTRA Storage
हर call को पहले Beacon read करना होता है (extra SLOAD = ~2,100 gas)।
2. Single Point of Failure
अगर Beacon compromise हो जाता है, सभी proxies compromise हो जाते हैं।
3. Limited Use Case
केवल तभी useful जब आपके पास dozens/hundreds of proxies हों (ex: game items, multi-tenant SaaS)।
Gas Costs
| Operation | Gas |
|-----------|-----|
| Deploy Beacon | ~300,000 |
| Deploy Proxy | ~150,000 |
| Call function (user) | +2,100 gas overhead |
| Upgrade (100 proxies) | ~30,000 (total, per proxy नहीं) |
Use case: अगर आपके पास 50+ proxies हैं, Beacon UUPS/Transparent से ज्यादा economical हो जाता है।
Direct Comparison
Synthetic Table
| Criterion | Transparent | UUPS | Beacon |
|---------|------------|------|--------|
| Gas deployment | High | Low | Medium |
| Gas per call | +2,600 | Baseline | +2,100 |
| Complexity | High | Medium | Medium |
| Security | Proven | Bug attention | Single point failure |
| Upgrade flexibility | Medium | High | High (mass) |
| Use case | Single proxy | Single proxy | Multiple proxies |
Code Comparison: Upgrade Flow
Transparent:
// ProxyAdmin (multisig) से
proxyAdmin.upgrade(transparentProxy, newImplementation);
UUPS:
// Contract के owner से (DAO हो सकता है)
MyContract(proxy).upgradeTo(newImplementation);
Beacon:
// Beacon के owner से
beacon.upgradeTo(newImplementation);
// → सभी proxies immediately newImplementation use करते हैं
Storage Collisions: Common Danger
किसी भी pattern में, storage layout error आपके data को destroy कर सकती है।
Collision Example
V1:
contract TokenV1 {
uint256 public totalSupply; // Slot 0
mapping(address => uint256) public balances; // Slot 1
}
V2 (FALSE - collision):
contract TokenV2 {
address public owner; // Slot 0 ← totalSupply के साथ COLLISION!
uint256 public totalSupply; // Slot 1 ← balances के साथ COLLISION!
mapping(address => uint256) public balances; // Slot 2
}
Upgrade के बाद:
totalSupplyको address के रूप में interpret किया जाता है
balancesको uint256 के रूप में interpret किया जाता है
- सभी data corrupt
Storage Gaps से Protection
contract TokenV1 {
uint256 public totalSupply;
mapping(address => uint256) public balances;
// Future variables के लिए 50 slots reserve
uint256[50] private __gap;
}
contract TokenV2 is TokenV1 {
// बिना collision के यहाँ variables add कर सकते हैं
address public owner;
// Gap को 1 से reduce (हमने 1 slot use की)
uint256[49] private __gap;
}
Best practice: अपने upgradeable contracts में हमेशा 50 slots का __gap include करें।
Initializers vs Constructors
Proxies constructors use नहीं कर सकते (deployment पर execute होते हैं, proxy के context में नहीं)।
FALSE:
contract Token {
address public owner;
constructor() {
owner = msg.sender; // Implementation में store, proxy में नहीं!
}
}
CORRECT:
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract Token is Initializable {
address public owner;
function initialize() public initializer {
owner = msg.sender; // Proxy में store ✓
}
}
initializer modifier guarantee करता है कि initialize केवल एक बार call किया जा सकता है।
Decision Matrix
Transparent Proxy चुनें अगर:
✅ आप maximum security चाहते हैं (2018 से proven pattern)
✅ आपके पास high-value project है (DeFi with TVL >$10M)
✅ आप usage simplicity prefer करते हैं (error का कम risk)
✅ Gas overhead acceptable है
❌ आप gas के लिए optimize कर रहे हैं
❌ आपको custom upgrade logic चाहिए
UUPS चुनें अगर:
✅ आप gas optimize कर रहे हैं (public apps, gaming)
✅ आप maximum flexibility चाहते हैं (custom upgrade logic)
✅ आपकी team proxies की subtleties master करती है
✅ आप OpenZeppelin Defender use करते हैं (errors से protection)
❌ आप proxies के साथ begin कर रहे हैं
❌ आप implementation error का zero risk चाहते हैं
Beacon Proxy चुनें अगर:
✅ आप 50+ identical contracts deploy करते हैं (ex: game items, multi-tenant SaaS)
✅ आप एक transaction में सभी contracts upgrade करना चाहते हैं
✅ आप per call +2,100 gas की overhead accept करते हैं
❌ आपके पास केवल एक contract है
❌ आप per proxy different implementations चाहते हैं
2026 Trends
Adoption statistics (base: top 100 DeFi protocols):
- Transparent Proxy: 45% (legacy projects)
- UUPS: 40% (new projects)
- Beacon Proxy: 10% (gaming, multi-contract apps)
- No proxy (immutable): 5% (radical decentralized protocols)
Evolution: UUPS gas optimization की वजह से ground gain कर रहा है, लेकिन Transparent critical protocols के लिए standard रहता है।
Final Recommendations
Standard DeFi project के लिए: Protection के लिए OpenZeppelin Defender के साथ UUPS।
Critical protocol (>$50M TVL) के लिए: Proven security के लिए Transparent Proxy।
Multi-instance application के लिए: Beacon Proxy (ex: 1000 types of items वाला game)।
Educational project के लिए: Transparent से start करें (error का कम risk), concepts master होने पर UUPS में migrate।
Pro tip: अपने खुद के proxies code करने की बजाय हमेशा OpenZeppelin implementations use करें। इन contracts को dozens of times audit किया गया है और battle-tested हैं।
Solingo पर, आप production में deploy करने से पहले interactive environment में तीनों proxy patterns के साथ experiment कर सकते हैं और storage layout की nuances समझ सकते हैं।