Comparison·8 min का पठन·Solingo द्वारा

Transparent vs UUPS vs Beacon Proxy — कौन सा Pattern उपयोग करें

Upgradeable smart contracts के लिए तीन proxy patterns का detailed comparison: Transparent Proxy, UUPS और Beacon Proxy। Mechanisms, gas costs, security और recommendations।

# 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 चाहते हैं

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 समझ सकते हैं।

Practice में लगाने के लिए तैयार हैं?

Solingo पर interactive exercises के साथ इन concepts को apply करें।

मुफ्त में शुरू करें