Proxy contracts स्मार्ट कॉन्ट्रैक्ट्स को उनकी स्टेट (state) बनाए रखने में सक्षम बनाते हैं, जबकि उनके लॉजिक (logic) को अपग्रेड करने की अनुमति देते हैं।
डिफ़ॉल्ट रूप से, स्मार्ट कॉन्ट्रैक्ट्स को अपग्रेड नहीं किया जा सकता है क्योंकि डिप्लॉय किए गए बाइटकोड (bytecode) को मॉडिफाई नहीं किया जा सकता है।
EVM में बाइटकोड को बदलने का एकमात्र तरीका एक नया कॉन्ट्रैक्ट डिप्लॉय करना है। हालाँकि, इस नए कॉन्ट्रैक्ट की स्टोरेज (storage) को पिछले कॉन्ट्रैक्ट के बारे में “कुछ भी पता” नहीं होगा। इसका मतलब है कि स्टोरेज में रखी गई पिछली वैल्यूज नए कॉन्ट्रैक्ट के लिए उपलब्ध नहीं होंगी।
Proxies जो समाधान पेश करते हैं, वह यह है कि स्टोरेज को एक कॉन्ट्रैक्ट में रखा जाए, और बिज़नेस लॉजिक और फंक्शनलिटी (बाइटकोड द्वारा प्रदान की गई) को किसी अन्य कॉन्ट्रैक्ट से प्राप्त किया जाए। यदि नई फंक्शनलिटी की आवश्यकता होती है, तो एक नया “लॉजिक कॉन्ट्रैक्ट (logic contract)” डिप्लॉय किया जाता है, लेकिन स्टोरेज कॉन्ट्रैक्ट वही रहता है।
जब स्टोरेज कॉन्ट्रैक्ट पर कॉल (call) की जाती है, तो स्टोरेज कॉन्ट्रैक्ट स्टेट अपडेट करने के लिए बस लॉजिक कॉन्ट्रैक्ट में मौजूद फंक्शन को delegatecalls कर देता है।
Proxies को समझने के लिए, delegatecall को समझना महत्वपूर्ण है, इसलिए कृपया पहले लिंक किए गए लेख को पढ़ें।
जिसे हम यहाँ “स्टोरेज कॉन्ट्रैक्ट” कह रहे हैं, वही proxy contract है।
इस लेख में, हम सिखाएंगे:
- Proxies कैसे काम करते हैं और उन्हें कैसे बनाया जाए
- एक proxy स्मार्ट कॉन्ट्रैक्ट को कैसे अपग्रेड करें
Disclaimer: यहाँ दिखाया गया proxy इम्प्लीमेंटेशन केवल सीखने के उद्देश्यों के लिए है और इसका उपयोग प्रोडक्शन (production) में नहीं किया जाना चाहिए। प्रोडक्शन-लेवल proxies के लिए, कृपया हमारी किताब Proxy Patterns के आगे के अध्याय देखें। लेकिन आगे के अध्यायों को पढ़ने से पहले एक बेहतर आधार बनाने के लिए आपको सबसे पहले यह अध्याय पढ़ना चाहिए।
Proxy contract क्या है?
एक proxy contract वह स्मार्ट कॉन्ट्रैक्ट है जो स्टेट वेरिएबल्स (state variables) को स्टोर करता है, जबकि अपना सारा लॉजिक एक या कई इम्प्लीमेंटेशन कॉन्ट्रैक्ट्स (implementation contracts) को डेलिगेट (delegate) कर देता है। यानी, एक proxy contract केवल स्टोरेज वेरिएबल्स को अपने पास रखता है, जबकि एक अलग कॉन्ट्रैक्ट का लॉजिक उन स्टोरेज वेरिएबल्स को अपडेट करता है।
आप एक proxy contract को अपने मोबाइल फोन पर मौजूद ऐप्स और डेटा के समान मान सकते हैं। फोन आपका पर्सनल डेटा—कॉन्टेक्ट्स, फोटो और ब्राउज़िंग हिस्ट्री—सुरक्षित रखता है, ठीक वैसे ही जैसे proxy अपनी स्टेट को बनाए रखता है। इम्प्लीमेंटेशन कॉन्ट्रैक्ट फोन के ऑपरेटिंग सिस्टम (OS) और ऐप्स की तरह है, जो इसकी फंक्शनलिटी और बिहेवियर के लिए ज़िम्मेदार है। जब OS या ऐप्स अपडेट होते हैं, तो फोन के फीचर्स बेहतर हो जाते हैं, लेकिन आपका डेटा जस का तस रहता है।
यह एनालॉजी (analogy) दर्शाती है कि कैसे एक proxy contract एक इम्प्लीमेंटेशन कॉन्ट्रैक्ट को फंक्शनलिटी डेलिगेट करते हुए अपनी स्टेट को बनाए रखता है।

एक proxy contract और उसका लॉजिक कॉन्ट्रैक्ट इस प्रकार सेटअप किए जाते हैं:
- आप एक proxy contract डिप्लॉय करते हैं
- फिर आप इम्प्लीमेंटेशन कॉन्ट्रैक्ट डिप्लॉय करते हैं
- आप इम्प्लीमेंटेशन कॉन्ट्रैक्ट का एड्रेस proxy की स्टोरेज में स्टोर करते हैं
- अब, proxy सभी कॉल्स को
DELEGATECALLके माध्यम से इम्प्लीमेंटेशन एड्रेस पर फॉरवर्ड कर देता है
Calls कैसे फॉरवर्ड की जाती हैं?
चूँकि proxy का अपना कोई लॉजिक नहीं होता है, इसलिए proxy contract पर की गई किसी भी कॉल को fallback फंक्शन द्वारा पकड़ लिया जाएगा। fallback फंक्शन उन मामलों को संभालता है जहाँ कोई फंक्शन कॉल कॉन्ट्रैक्ट में परिभाषित किसी भी फंक्शन से मेल नहीं खाती है।
इसके बाद proxy उसी calldata का उपयोग करके इम्प्लीमेंटेशन को delegatecall करेगा जो proxy को प्राप्त हुआ था, जैसा कि नीचे दिए गए आरेख में दिखाया गया है:

Proxy contract हमेशा उसी calldata का उपयोग करके इम्प्लीमेंटेशन को delegatecalls करता है जो उसे प्राप्त हुआ था।
रिव्यु के तौर पर delegatecall पर हमारे लेख से यहाँ एक एनीमेशन दिया गया है:
Proxy contracts क्यों?
Proxy contracts के दो मुख्य यूज़ केस (use cases) हैं:
1. अपग्रेडिबिलिटी (Upgradeability)
किसी कॉन्ट्रैक्ट को अपग्रेड करने की क्षमता proxy contracts का सबसे आम यूज़ केस है। एक proxy पैटर्न आपको ऐसे कॉन्ट्रैक्ट्स बनाने की अनुमति देता है जिन्हें मौजूदा कॉन्ट्रैक्ट की स्टेट या एड्रेस को बाधित किए बिना अपग्रेड (नए लॉजिक या फीचर्स को शामिल) किया जा सकता है।
दूसरी ओर, एक नॉन-अपग्रेडेबल (non-upgradeable) कॉन्ट्रैक्ट के लिए हर बार जब आप कोई बग ठीक करते हैं या नए फीचर्स जोड़ते हैं, तो आपको सभी यूजर्स, वॉलेट प्रोवाइडर्स और एक्सचेंजों को एक नए स्मार्ट कॉन्ट्रैक्ट एड्रेस पर माइग्रेट (migrate) करने के लिए मनाना पड़ता है।
2. डिप्लॉयमेंट गैस कॉस्ट (gas cost) बचाना
यदि किसी कॉन्ट्रैक्ट की कई कॉपियाँ डिप्लॉय करने की आवश्यकता है, तो Proxies गैस बचा सकते हैं, क्योंकि सभी proxies अपनी अलग स्टेट रखते हुए एक ही लॉजिक कॉन्ट्रैक्ट का उपयोग कर सकते हैं। हर कॉपी के लिए पूरा कॉन्ट्रैक्ट लॉजिक डिप्लॉय करने के बजाय, आप एक सिंगल इम्प्लीमेंटेशन कॉन्ट्रैक्ट डिप्लॉय करते हैं, और सभी proxies इसके साथ इंटरेक्ट करने के लिए delegatecall का उपयोग करते हैं। चूँकि लॉजिक बहुत सरल होता है, इसलिए डिप्लॉय किया गया बाइटकोड बहुत छोटा होता है और इस प्रकार इसे डिप्लॉय करना सस्ता होता है। इस पैटर्न को Minimal Proxy Pattern कहा जाता है (इसके बारे में लेख में आगे और बताया गया है)।
एक अपग्रेडेबल स्मार्ट कॉन्ट्रैक्ट कैसे डिप्लॉय करें (प्रोडक्शन के लिए नहीं)
आइए एक साधारण proxy contract बनाकर शुरू करें जो एक सिंगल हार्डकोडेड (hardcoded) इम्प्लीमेंटेशन एड्रेस को delegatecalls करता है। यह हमें इसे अपग्रेडेबल बनाने से पहले बेसिक पैटर्न को समझने में मदद करेगा।
1. अपना इम्प्लीमेंटेशन कॉन्ट्रैक्ट डिप्लॉय करें
आइए नीचे दिए गए कॉन्ट्रैक्ट को अपना इम्प्लीमेंटेशन कॉन्ट्रैक्ट मानें। यह दो नंबरों को आर्गुमेंट्स के रूप में लेता है और उनके योग (sum) को एक event के रूप में एमिट (emit) करता है।
contract Implementation {
event Result(uint256 newValue);
function addNumbers(uint256 number1, uint256 number2) public returns (uint256 result ) {
result = number1 + number2;
emit Result(result);
}
}
हम नीचे दिखाए गए अनुसार Remix का उपयोग करके इम्प्लीमेंटेशन कॉन्ट्रैक्ट डिप्लॉय करते हैं। डिप्लॉयमेंट के बाद, हम एड्रेस को कॉपी करते हैं:

2. एक proxy contract डिप्लॉय करें और इम्प्लीमेंटेशन एड्रेस सेट करें
अब हम Proxy कॉन्ट्रैक्ट में Implementation कॉन्ट्रैक्ट का एड्रेस स्टोर करके Proxy कॉन्ट्रैक्ट को डिप्लॉय कर सकते हैं।
// Replace this with the implementation address
// you get when you deployed the implementation
// contract
address immutable implementation = 0x44fE319Fc0C2d3e09F9a86AF94eEabB6173A1d58;
नीचे हम एक proxy contract का उदाहरण दिखा रहे हैं:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;
contract Proxy {
// Change the implementation address to the one you get after deploying the
// implementation contract
address immutable implementation = 0x44fE319Fc0C2d3e09F9a86AF94eEabB6173A1d58;
fallback(bytes calldata data) external returns (bytes memory) {
(bool success, bytes memory result) = implementation.delegatecall(data);
require(success, "Delegatecall failed");
return result;
}
}
नीचे दिए गए आरेख में दिखाए गए अनुसार Remix पर proxy contract डिप्लॉय करें।

अपने कॉन्ट्रैक्ट की टेस्टिंग/इंटरैक्ट करना
जब कॉन्ट्रैक्ट डिप्लॉयमेंट पूरा हो जाता है, तो अगला कदम proxy contract के साथ इंटरेक्ट करना होगा। हम आपके कॉन्ट्रैक्ट के साथ इंटरेक्ट करने के दो तरीकों का पता लगाएंगे।
1. Remix में Low Level Interaction इंटरफ़ेस का उपयोग करके proxy contract के साथ इंटरेक्ट करना
Remix में proxy contract के साथ इंटरेक्ट करने का पहला तरीका Low Level Interaction इंटरफ़ेस का उपयोग करना है। इसमें हमारे टार्गेट फंक्शन के लिए एक calldata बनाना और इसे calldata इनपुट बॉक्स में पास करना शामिल है।
तो, दो नंबरों 5 और 4 को जोड़ने के लिए addNumbers फंक्शन को ट्रिगर करने के लिए, हम नीचे दिखाए गए अनुसार फंक्शन और उसके पैरामीटर्स की ABI encoding करके calldata का निर्माण करेंगे:
function seeEncoding() external pure returns (bytes memory) {
return abi.encodeWithSignature("addNumbers(uint256,uint256)", 5,4);
}
इसका परिणाम नीचे दिया गया कोड होगा:
0xef9fc50b00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004
अब जब हमने calldata बना लिया है, तो आइए इसका उपयोग proxy contract में फंक्शन को कॉल करने के लिए करें।
इनपुट बॉक्स में calldata पेस्ट करें। हमें परिणाम 9 मिलने की उम्मीद करनी चाहिए क्योंकि 5+4=9 होता है, जैसा कि नीचे दिए गए स्क्रीनशॉट में दिखाया गया है:

भले ही Proxy कॉन्ट्रैक्ट में इवेंट्स एमिट करने का कोई लॉजिक नहीं है, फिर भी जब हमने proxy को calldata भेजा तो हम एक इवेंट एमिट होते हुए देखते हैं। ऐसा इसलिए है क्योंकि इवेंट एमिट करने वाला लॉजिक proxy द्वारा delegatecall किया गया था।
स्पष्ट रूप से यह प्रक्रिया आपके कॉन्ट्रैक्ट्स का परीक्षण करने के लिए थोड़ी जटिल लगती है, खासकर यदि हमें मैन्युअली अपने स्वयं के calldata को एन्कोड करना हो। एक अधिक सरल विकल्प यह है कि Implementation कॉन्ट्रैक्ट के ABI का उपयोग करके Proxy कॉन्ट्रैक्ट के साथ इंटरेक्ट किया जाए।
2. Remix में Implementation कॉन्ट्रैक्ट के ABI का उपयोग करके Proxy कॉन्ट्रैक्ट के साथ इंटरेक्ट करना
डिप्लॉयमेंट के बाद proxy contract को सेटअप करने के लिए इन स्टेप्स को फॉलो करें ताकि आप इम्प्लीमेंटेशन कॉन्ट्रैक्ट के ABI के माध्यम से इसके साथ इंटरेक्ट कर सकें:
CONTRACTड्रॉपडाउन में,Implementationकॉन्ट्रैक्ट चुनें।

Proxyकॉन्ट्रैक्ट एड्रेस कॉपी करें और इसेAt Addressइनपुट बॉक्स में पेस्ट करें।

- कॉन्ट्रैक्ट के साथ इंटरेक्ट करने के लिए
At Addressबटन पर क्लिक करें, जैसा कि नीचे दिए गए आरेख में दिखाया गया है।

अब, आप नीचे दिए गए आरेख में दिखाए गए अनुसार addNumbers फंक्शन के साथ इंटरेक्ट करने में सक्षम होंगे:

नोट: भले ही Remix ने उस कॉन्ट्रैक्ट को Implementation के रूप में लेबल किया है जिसके साथ हम इंटरेक्ट कर रहे हैं, यह वास्तव में Implementation कॉन्ट्रैक्ट्स के ABI का उपयोग करने वाला Proxy कॉन्ट्रैक्ट है।
जैसा कि हम देख सकते हैं, जब यूजर Proxy कॉन्ट्रैक्ट के साथ इंटरेक्ट करता है और addNumbers फंक्शन को कॉल करने का प्रयास करता है, तो यह fallback फंक्शन को ट्रिगर करता है क्योंकि addNumbers फंक्शन Proxy में मौजूद नहीं है। एक बार ट्रिगर होने के बाद, fallback फंक्शन delegatecall का उपयोग करके एग्जीक्यूशन (execution) को Implementation कॉन्ट्रैक्ट पर फॉरवर्ड कर देता है, जहाँ फंक्शन को परिभाषित किया गया है।
नीचे दी गई स्क्रीन रिकॉर्डिंग उपरोक्त स्टेप्स को सारांशित करती है:
अब तक, हमने एक बेसिक proxy contract देखा है जो एक हार्डकोडेड (hardcoded) इम्प्लीमेंटेशन एड्रेस पर कॉल्स डेलिगेट करता है। हालाँकि, यह दृष्टिकोण अपग्रेडेबल नहीं है, क्योंकि immutable कीवर्ड के कारण इम्प्लीमेंटेशन एड्रेस कॉन्ट्रैक्ट बाइटकोड में फिक्स हो जाता है।
address immutable implementation = 0x44fE319Fc0C2d3e09F9a86AF94eEabB6173A1d58;
Proxy के इम्प्लीमेंटेशन को अपडेट करना
Proxy कॉन्ट्रैक्ट को अपग्रेडेबल बनाने के लिए, हमें इम्प्लीमेंटेशन एड्रेस को इस तरह से स्टोर करने की आवश्यकता है कि उसे डिप्लॉयमेंट के बाद अपडेट किया जा सके। हम proxy कॉन्ट्रैक्ट में एक setImplementation फंक्शन जोड़कर ऐसा कर सकते हैं:
function setImplementation(address _implementation) public onlyOwner {
implementation = _implementation;
}
अब, इम्प्लीमेंटेशन एड्रेस को हार्डकोड करने के बजाय, हम इसे एक स्टेट वेरिएबल implementation में स्टोर करते हैं। इस तरह, जब आवश्यक हो हम इसे अपडेट कर सकते हैं।
contract Proxy {
// Store the implementation contract address
address implementation;
function setImplementation(address _implementation) public {
implementation = _implementation;
}
fallback(bytes calldata data) external returns (bytes memory) {
(bool success, bytes memory result) = implementation.delegatecall(data);
require(success, "Delegatecall failed");
return result;
}
}
सुरक्षा उद्देश्यों के लिए, हमें यह सुनिश्चित करने की आवश्यकता है कि केवल एक एडमिन (admin) ही इम्प्लीमेंटेशन एड्रेस को अपडेट कर सके। हम एक admin स्टेट वेरिएबल को शामिल करके इसे प्राप्त करते हैं:
contract Proxy {
address public implementation;
address public admin;
...
और एक मॉडिफायर (modifier) के साथ setImplementation फंक्शन के एक्सेस को प्रतिबंधित करते हैं:
modifier onlyOwner() {
require(msg.sender == admin, "Not the contract owner");
_;
}
Storage collision की समस्या
अब हमारे proxy कॉन्ट्रैक्ट में implementation, admin, और number (हमने स्टोरेज कोलिज़न की समस्या को दर्शाने के लिए number को शामिल किया है) स्टोरेज वेरिएबल्स शामिल हैं और स्टोरेज लेआउट अब इस तरह दिखता है:
contract Proxy {
address public implementation;
address public admin;
uint256 public number;
...
और हमारे इम्प्लीमेंटेशन कॉन्ट्रैक्ट में, हमारे पास number स्टेट वेरिएबल है:
contract Implementation {
uint256 public number;
...
इससे एक स्टोरेज कोलिज़न (storage collision) होगा। जब हम proxy कॉन्ट्रैक्ट में number स्टेट वेरिएबल को अपडेट करने का प्रयास करेंगे, तो हम implementation एड्रेस स्टेट को ओवरराइट (overwrite) कर देंगे, जो कि हम नहीं चाहते हैं!
Solidity में, स्टोरेज वेरिएबल्स को कॉन्ट्रैक्ट में उनके डिक्लेरेशन (declaration) के क्रम के आधार पर फिक्स्ड storage slots असाइन किए जाते हैं। इसका मतलब है कि यदि proxy और इम्प्लीमेंटेशन में स्टोरेज वेरिएबल्स का लेआउट मेल नहीं खाता है, तो कॉन्फ्लिक्ट्स (conflicts) होंगे।
हमारे मामले में:
- Proxy कॉन्ट्रैक्ट
implementationएड्रेस को slot 0 पर,adminको slot 1 पर, औरnumberको slot 2 पर स्टोर करता है। - इम्प्लीमेंटेशन कॉन्ट्रैक्ट में,
numberवेरिएबल slot 0 में स्टोर होता है।
इसके कारण एक कॉन्फ्लिक्ट पैदा होता है क्योंकि जब इम्प्लीमेंटेशन कॉन्ट्रैक्ट अपने number वेरिएबल को अपडेट करने का प्रयास करता है, तो यह इसके बजाय proxy कॉन्ट्रैक्ट में implementation एड्रेस को मॉडिफाई कर देता है, जो उसी स्लॉट (slot 0) पर स्टोर होता है।

इससे एक अनपेक्षित बिहेवियर उत्पन्न होता है—आप proxy में number को अपडेट करना चाहते हैं, लेकिन आप वास्तव में स्टोरेज में implementation एड्रेस को ओवरराइट कर रहे हैं।
हमारे लेख Storage Slots in Solidity: Storage Allocation and Low-level assembly storage operations और Storage Slot III (Complex Types) विस्तार से बताते हैं कि उपयोगी आरेखों और एनिमेशन के साथ Solidity में स्टोरेज स्लॉट कैसे काम करते हैं।
आइए उदाहरण के रूप में निम्नलिखित कॉन्ट्रैक्ट का उपयोग करें:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;
contract Proxy {
address public implementation;
address public admin;
uint256 public number;
constructor() {
admin = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == admin, "Not the contract owner");
_;
}
function setImplementation(address _implementation) public onlyOwner {
implementation = _implementation;
}
fallback(bytes calldata data) external returns (bytes memory) {
require(implementation != address(0), "Implementation not set");
(bool success, bytes memory result) = implementation.delegatecall(data);
require(success, "Delegatecall failed");
return result;
}
}
contract Implementation {
uint256 public number;
function increment() public {
number++;
}
}
आप ध्यान देंगे कि इंक्रीमेंट (increment) सही ढंग से काम नहीं करेगा क्योंकि यह स्टोरेज में number के बजाय इम्प्लीमेंटेशन कॉन्ट्रैक्ट के एड्रेस को अपडेट कर रहा है:

हम proxies में इस storage collision की समस्या को कैसे हल करते हैं?
एक तरीका यह है कि एक रैंडम (random) स्लॉट चुना जाए ताकि कोलिज़न (collision) की संभावना बेहद कम हो जाए। हम ऐसे स्लॉट को कैसे चुनते हैं, इसके बारे में अधिक जानकारी ERC-1967 में दी गई है।
इसलिए, ERC-1967 कन्वेंशन का पालन करते हुए, हम implementation एड्रेस को स्टोर करने के लिए नीचे दिए गए स्लॉट का उपयोग करेंगे:
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
स्लॉट को इससे स्यूडोरैंडमली (pseudorandomly) डिराइव किया गया है:
bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
और हम admin एड्रेस को स्टोर करने के लिए नीचे दिए गए स्लॉट का उपयोग करेंगे:
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
इससे डिराइव किया गया:
bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
इन विशिष्ट स्टोरेज स्लॉट्स को पढ़ने (read) या लिखने (write) के लिए, आपको इनलाइन असेंबली (inline assembly) में क्रमशः sload और sstore का उपयोग करने की आवश्यकता होगी।
नीचे दिया गया कोड हमारे शुरुआती proxy कॉन्ट्रैक्ट का एक संशोधित संस्करण है, जो अब ERC-1967 स्टैंडर्ड द्वारा परिभाषित स्टोरेज स्लॉट्स का उपयोग करता है ताकि यह सुनिश्चित हो सके कि proxy और इम्प्लीमेंटेशन कॉन्ट्रैक्ट्स के बीच कोई स्टोरेज कोलिज़न न हो।
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
contract Proxy {
/**
* @dev Storage slot for the implementation address.
* This is derived from `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)`.
*/
bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Storage slot for the admin address.
* This is derived from `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)`.
*/
bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016eaf15eb9e8e9f03347e2db6a3ec1e1cb0;
// Initialize proxy with the owner
constructor() {
address admin = msg.sender;
assembly {
// Store admin in the ERC-1967 admin slot
sstore(_ADMIN_SLOT, admin)
}
}
modifier onlyOwner() {
address admin;
assembly {
// Load admin from the ERC-1967 admin slot
admin := sload(_ADMIN_SLOT)
}
require(msg.sender == admin, "Not the contract owner");
_;
}
function setImplementation(address _implementation) public onlyOwner {
assembly {
// Store implementation in the ERC-1967 implementation slot
sstore(_IMPLEMENTATION_SLOT, _implementation)
}
}
fallback(bytes calldata data) external payable returns (bytes memory) {
address implementation;
assembly {
// Load implementation from the ERC-1967 implementation slot
implementation := sload(_IMPLEMENTATION_SLOT)
}
require(implementation != address(0), "Implementation not set");
(bool success, bytes memory result) = implementation.delegatecall(data);
require(success, "Delegatecall failed");
return result;
}
}
contract Implementation {
uint256 public number;
function increment() public {
number++;
}
}
अब, यदि हम इस कॉन्ट्रैक्ट को डिप्लॉय करते हैं और इसे रन करते हैं, तो हमें वांछित परिणाम मिलेगा जैसा कि नीचे दिखाया गया है:

हम अपने Storage Slots for Proxies लेख में EIP-1967 पर विस्तार से चर्चा करते हैं, और यह इस किताब का अगला अध्याय है।
निष्कर्ष
इस लेख में, हमने proxy contracts के कॉन्सेप्ट, उनके महत्व, और कैसे वे अपग्रेडिबिलिटी को सक्षम करते हैं और Solidity स्मार्ट कॉन्ट्रैक्ट्स की डिप्लॉयमेंट कॉस्ट (deployment costs) को कम करते हैं, इसका पता लगाया है।
इस लेख की कुछ प्रमुख बातें (key takeaways) यहाँ दी गई हैं:
DELEGATECALLऑपकोड (opcode) proxies के साथ अपग्रेडिबिलिटी को संभव बनाता है।- Proxy contracts (अपग्रेडेबल और नॉन-अपग्रेडेबल दोनों) स्टोरेज को होल्ड करते हैं, जिसमें इम्प्लीमेंटेशन एड्रेस शामिल है। इम्प्लीमेंटेशन कॉन्ट्रैक्ट्स लॉजिक को होल्ड करते हैं।
- अपग्रेडेबल Proxy स्टोरेज, इम्प्लीमेंटेशन एड्रेस को होल्ड करता है, और इम्प्लीमेंटेशन एड्रेस को अपडेट करने के लिए एक सेटर (setter) फंक्शन प्रदान करता है। इम्प्लीमेंटेशन केवल लॉजिक को होल्ड करता है।
आगे पढ़ने के लिए सुझाव: