Beacon Proxy एक स्मार्ट कॉन्ट्रैक्ट अपग्रेड पैटर्न है जहाँ कई प्रॉक्सी समान implementation कॉन्ट्रैक्ट का उपयोग करते हैं, और सभी प्रॉक्सी को एक ही ट्रांजेक्शन में अपग्रेड किया जा सकता है। यह लेख बताता है कि यह प्रॉक्सी पैटर्न कैसे काम करता है।
पूर्व आवश्यकताएँ (Prerequisites)
हम यह मानकर चलेंगे कि आप पहले से ही जानते हैं कि minimal proxy कैसे काम करता है और शायद UUPS या Transparent प्रॉक्सी के बारे में भी जानते हैं।
Beacon Proxies की आवश्यकता (Motivation)
आमतौर पर, एक प्रॉक्सी पैटर्न एक सिंगल implementation कॉन्ट्रैक्ट और एक सिंगल प्रॉक्सी कॉन्ट्रैक्ट का उपयोग करता है। हालाँकि, यह संभव है कि कई प्रॉक्सी एक ही implementation का उपयोग करें।

यह समझने के लिए कि हम ऐसा क्यों चाहेंगे, आइए एक पूरी तरह से ऑन-चेन (on-chain) गेम की कल्पना करें। यह गेम प्रत्येक उपयोगकर्ता खाते (user account) को एक अलग कॉन्ट्रैक्ट के रूप में स्टोर करना चाहता है, ताकि खातों को आसानी से विभिन्न वॉलेट्स में ट्रांसफर किया जा सके और एक वॉलेट में कई खाते हो सकें। प्रत्येक प्रॉक्सी अपने संबंधित स्टोरेज वेरिएबल्स में खाते की जानकारी स्टोर करता है।
इसे implement करने के कुछ तरीके हो सकते हैं:
- Minimal Proxy Standard (EIP1167) का उपयोग करें और प्रत्येक खाते को एक क्लोन के रूप में डिप्लॉय (deploy) करें।
- UUPS या Transparent प्रॉक्सी पैटर्न का उपयोग करें और प्रत्येक खाते के लिए एक प्रॉक्सी डिप्लॉय करें।
ज़्यादातर मामलों में कोई भी विकल्प काम करेगा, लेकिन क्या हो अगर आप खाते में नई कार्यक्षमता (functionality) जोड़ना चाहें?
Minimal proxy standard के मामले में, आपको पूरे सिस्टम को फिर से डिप्लॉय करना होगा और सभी को सामाजिक रूप से माइग्रेट करना होगा क्योंकि क्लोन अपग्रेड करने योग्य (upgradeable) नहीं होते हैं।
पारंपरिक (Traditional) प्रॉक्सी अपग्रेड करने योग्य होते हैं लेकिन आपको प्रत्येक प्रॉक्सी को एक-एक करके अपग्रेड करना होगा। अधिक खाते होने पर यह महंगा साबित होगा।
जब इनकी संख्या बहुत अधिक होती है, तो क्लोन और प्रॉक्सी दोनों को अपग्रेड करना एक परेशानी का काम होता है।
Beacon पैटर्न को इसी समस्या को हल करने के लिए डिज़ाइन किया गया है: यह आपको एक नया implementation कॉन्ट्रैक्ट डिप्लॉय करने और सभी प्रॉक्सी को एक साथ अपग्रेड करने की अनुमति देता है।
इसका मतलब है कि beacon पैटर्न आपको खाते का एक नया implementation डिप्लॉय करने और सभी प्रॉक्सी को एक ही बार में अपग्रेड करने की अनुमति देगा।
उच्च स्तर (high level) से देखा जाए तो, यह मानक (standard) आपको प्रति implementation कॉन्ट्रैक्ट असीमित संख्या में प्रॉक्सी बनाने की अनुमति देता है, और फिर भी आसानी से अपग्रेड करने में सक्षम बनाता है।
Beacon कैसे काम करता है
जैसा कि नाम से पता चलता है, इस मानक के लिए एक beacon की आवश्यकता होती है, जिसे OpenZeppelin “UpgradeableBeacon” कहता है और इसे UpgradeableBeacon.sol में implement करता है।
Beacon एक स्मार्ट कॉन्ट्रैक्ट है जो एक public फंक्शन के माध्यम से प्रॉक्सी को वर्तमान implementation एड्रेस प्रदान करता है। वर्तमान implementation एड्रेस के संबंध में प्रॉक्सी के लिए beacon ही सत्य का स्रोत (source of truth) है, यही कारण है कि इसे “beacon” कहा जाता है।
जब किसी प्रॉक्सी को एक इनकमिंग ट्रांजेक्शन प्राप्त होता है, तो प्रॉक्सी सबसे पहले वर्तमान implementation एड्रेस लाने के लिए beacon पर view फंक्शन implementation() को कॉल करता है, और फिर प्रॉक्सी उस एड्रेस पर delegatecalls करता है। यही वह चीज़ है जो beacon को सत्य के स्रोत के रूप में कार्य करने की अनुमति देती है कि implementation कहाँ स्थित है।

कोई भी अतिरिक्त प्रॉक्सी इसी पैटर्न का पालन करेगा: वे सबसे पहले implementation() का उपयोग करके beacon से implementation एड्रेस प्राप्त करते हैं और फिर उस एड्रेस पर delegatecall करते हैं।
नोट: प्रॉक्सी जानते हैं कि implementation() को कहाँ कॉल करना है क्योंकि वे beacon के एड्रेस को एक immutable वेरिएबल में स्टोर करते हैं। हम इस तंत्र (mechanism) को बाद में और अधिक विस्तार से समझाएंगे।
यह पैटर्न अत्यधिक स्केलेबल (scalable) है क्योंकि प्रत्येक अतिरिक्त प्रॉक्सी बस beacon से implementation एड्रेस पढ़ता है और फिर delegatecall का उपयोग करता है।

हालाँकि beacon प्रॉक्सी पैटर्न में अधिक कॉन्ट्रैक्ट्स शामिल होते हैं, लेकिन प्रॉक्सी स्वयं UUPS या Transparent Upgradeable Proxies की तुलना में सरल होता है।
Beacon प्रॉक्सी हमेशा वर्तमान implementation एड्रेस प्राप्त करने के लिए उसी beacon एड्रेस को कॉल करते हैं, इसलिए उन्हें इस बात की चिंता करने की आवश्यकता नहीं है कि एडमिन कौन है या implementation एड्रेस को कैसे बदला जाए।
एक साथ कई प्रॉक्सी को अपग्रेड करना
चूँकि सभी प्रॉक्सी beacon के स्टोरेज से implementation एड्रेस प्राप्त करते हैं, इसलिए स्टोरेज स्लॉट में एड्रेस बदलने से सभी प्रॉक्सी नए एड्रेस पर delegatecall करने लगते हैं, जिससे वे तुरंत “रीरूट” (reroute) हो जाते हैं।
सभी प्रॉक्सी को एक साथ अपग्रेड करने के लिए:
- एक नया implementation कॉन्ट्रैक्ट डिप्लॉय करें
- Beacon के स्टोरेज में नया implementation एड्रेस सेट करें
नया implementation एड्रेस सेट करने का काम beacon पर upgradeTo(address newImplementation) को कॉल करके और नए एड्रेस को एक आर्गुमेंट के रूप में पास करके किया जाता है। upgradeTo() UpgradeableBeacon.sol (beacon) पर दो public फंक्शन में से एक है। दूसरा public (view) फंक्शन implementation() है जिसका उल्लेख हमने पहले किया था।
नोट: upgradeTo() में एक onlyOwner मॉडिफायर (modifier) होता है जिसे UpgradeableBeacon.sol (beacon) के कंस्ट्रक्टर (constructor) में सेट किया जाता है।
/**
* @dev Upgrades the beacon to a new implementation.
*
* Emits an {Upgraded} event.
*
* Requirements:
*
* - msg.sender must be the owner of the contract.
* - `newImplementation` must be a contract.
*/
function upgradeTo(address newImplementation) public virtual onlyOwner {
_setImplementation(newImplementation);
}
upgradeTo() एक internal फंक्शन _setImplementation(address newImplementation) (जो कि beacon पर ही है) को कॉल करता है, जो यह जाँचता है कि नया implementation एड्रेस एक कॉन्ट्रैक्ट है या नहीं और फिर beacon में एड्रेस स्टोरेज वेरिएबल, _implementation, को नए implementation एड्रेस पर सेट कर देता है।
/**
* @dev Sets the implementation contract address for this beacon
*
* Requirements:
*
* - `newImplementation` must be a contract.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
_implementation = newImplementation;
}
अब जब beacon के स्टोरेज में implementation एड्रेस बदल गया है, तो सभी प्रॉक्सी beacon में नए एड्रेस को पढ़ेंगे और अपने delegatecall को नए implementation की ओर रूट कर देंगे।
अपग्रेड करने का यह तरीका सरल है क्योंकि आप केवल beacon को, और इस तरह प्रॉक्सी को, एक नए implementation की ओर “पॉइंट” (point) कर रहे हैं। यदि आपको परिवर्तनों को रिवर्ट (revert) करने की आवश्यकता हो तो आप implementation को वापस पिछले संस्करण (version) पर भी पॉइंट कर सकते हैं (स्टोरेज टकराव (storage collisions) का ध्यान रखें)।

प्रॉक्सी कॉन्ट्रैक्ट का कोड वॉकथ्रू
भ्रम से बचने के लिए, हम स्मार्ट कॉन्ट्रैक्ट प्रॉक्सी को संदर्भित (refer) करने के लिए “BeaconProxy” शब्दावली का उपयोग करते हैं और डिज़ाइन पैटर्न को संदर्भित करने के लिए “beacon proxy” का उपयोग करते हैं। अब हम उस प्रॉक्सी कॉन्ट्रैक्ट पर चर्चा करेंगे जिसे OpenZeppelin “BeaconProxy” कहता है और BeaconProxy.sol में implement करता है।
OpenZeppelin का BeaconProxy Proxy.sol से इनहेरिट (inherit) करता है और अधिक कार्यक्षमता (functionality) जोड़ता है:
- यह beacon कॉन्ट्रैक्ट के एड्रेस को
_beaconमें स्टोर करता है _beaconवेरिएबल को वापस (return) करने के लिए एक_getBeacon()फंक्शन जोड़ा गया है_beaconएड्रेस पर.implementation()को कॉल करने के लिए_implementation()फंक्शन को ओवरराइड (override) किया गया है_beaconवेरिएबल को सेट करने के लिए एक कंस्ट्रक्टर जोड़ा गया है औरdataपैरामीटर प्रॉक्सी को इनिशियलाइज़ (initialize) करता है
नीचे OpenZeppelin द्वारा implement किया गया BeaconProxy दिया गया है जिसमें से कमेंट्स हटा दिए गए हैं
contract BeaconProxy is Proxy {
address private immutable _beacon;
constructor(address beacon, bytes memory data) payable {
ERC1967Utils.upgradeBeaconToAndCall(beacon, data);
_beacon = beacon;
}
function _implementation() internal view virtual override returns (address) {
return IBeacon(_getBeacon()).implementation();
}
function _getBeacon() internal view virtual returns (address) {
return _beacon;
}
}
_implementation() फंक्शन को ओवरराइड किया गया है क्योंकि Proxy.sol delegatecall से पहले implementation एड्रेस प्राप्त करने के लिए उस फंक्शन को कॉल करता है।
BeaconProxy का कंस्ट्रक्टर दो उद्देश्यों की पूर्ति करता है:
_beaconएड्रेस सेट करनाdataके साथ प्रॉक्सी को इनिशियलाइज़ करना
इस वैकल्पिक (optional) data का उपयोग implementation के लिए delegatecall में किया जाता है, जो प्रॉक्सी के स्टोरेज के इनिशियलाइज़ेशन (initialization) को सक्षम करता है। हमारे गेम के उदाहरण में, इसका अर्थ खिलाड़ी के शुरुआती आंकड़ों (stats) के साथ खाते (प्रॉक्सी) को इनिशियलाइज़ करना हो सकता है। मूल रूप से, data आर्गुमेंट प्रॉक्सी के लिए Solidity कंस्ट्रक्टर के रूप में कार्य करता है: data का उपयोग implementation के लिए delegatecall में किया जाता है ताकि implementation लॉजिक प्रॉक्सी स्टोरेज वेरिएबल्स को कॉन्फ़िगर कर सके।
function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
_setBeacon(newBeacon);
emit IERC1967.BeaconUpgraded(newBeacon);
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
} else {
_checkNonPayable();
}
}
ERC1967 और BeaconProxy.sol
ब्लॉक एक्सप्लोरर्स (block explorers) को यह बताने के लिए कि BeaconProxy एक प्रॉक्सी है, इसे ERC-1967 स्पेसिफिकेशन का पालन करना होगा। चूँकि यह विशेष रूप से एक beacon प्रॉक्सी है, इसलिए इसे Beacon के एड्रेस को स्टोरेज स्लॉट: 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50 में स्टोर करने की आवश्यकता है, जिसकी गणना bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1) से की जाती है।
Transparent Upgradeable Proxy के समान, इस स्टोरेज एड्रेस का वास्तव में BeaconProxy द्वारा उपयोग नहीं किया जाता है। यह ब्लॉक एक्सप्लोरर्स के लिए केवल एक संकेत (signal) है कि कॉन्ट्रैक्ट एक Beacon Proxy है। वास्तविक implementation एड्रेस को gas optimization के उद्देश्यों के लिए एक immutable वेरिएबल में स्टोर किया जाता है; beacon का एड्रेस कभी नहीं बदलता है।
EIP2930
इस पैटर्न के साथ हमेशा access list ट्रांजेक्शन्स का उपयोग करें, क्योंकि जब आप क्रॉस-कॉन्ट्रैक्ट कॉल (cross-contract call) करते हैं और किसी अन्य कॉन्ट्रैक्ट के स्टोरेज तक पहुँचते हैं तो आप गैस (gas) बचा सकते हैं। विशेष रूप से, प्रॉक्सी beacon को कॉल कर रहा है और स्टोरेज से implementation एड्रेस प्राप्त कर रहा है। Beacon Proxy के लिए एक्सेस लिस्ट बेंचमार्किंग (access list benchmarking) यहाँ देखी जा सकती है।
कई BeaconProxies डिप्लॉय करना
कई BeaconProxies को मैन्युअली (manually) डिप्लॉय करना एक परेशानी भरा काम होगा। यहीं पर फैक्ट्री (factory) कॉन्ट्रैक्ट काम आता है। फैक्ट्री नए प्रॉक्सी डिप्लॉय करती है और उनके कंस्ट्रक्टर में beacon एड्रेस सेट करती है।
OpenZeppelin अपने beacon पैटर्न में एक मानक (standard) फैक्ट्री कॉन्ट्रैक्ट की आवश्यकता नहीं रखता है और न ही प्रदान करता है। हालाँकि, व्यवहार में (in practice), एक फैक्ट्री कॉन्ट्रैक्ट नए प्रॉक्सी को डिप्लॉय करने में मदद करता है।
नीचे एक उदाहरण फैक्ट्री दी गई है। फैक्ट्री beacon के एड्रेस को स्टोर करती है और इसमें नए प्रॉक्सी बनाने के लिए एक फंक्शन शामिल है जो उस beacon का उपयोग करते हैं। createBeaconProxy() फंक्शन BeaconProxy के कंस्ट्रक्टर को पास करने के लिए इनपुट के रूप में data लेता है। प्रॉक्सी को डिप्लॉय करने के बाद, यह प्रॉक्सी का एड्रेस वापस (return) कर देता है।
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {BeaconProxy} from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
/// @dev THIS CONTRACT IS FOR TEACHING PURPOSES ONLY
contract ExampleFactory {
address public immutable beacon;
constructor(address Beacon) {
beacon = Beacon;
}
function createBeaconProxy(bytes memory data) external returns (address) {
BeaconProxy proxy = new BeaconProxy(beacon, data);
return address(proxy);
}
}
अब जब हम समझ गए हैं कि फैक्ट्री कॉन्ट्रैक्ट के साथ प्रॉक्सी कैसे डिप्लॉय किए जाते हैं, तो आइए देखें कि यह समग्र संरचना (overall structure) में कैसे फिट बैठता है।

और beacon पैटर्न डिज़ाइन करने के लिए बस इन्हीं कॉन्ट्रैक्ट्स की आवश्यकता होती है:
- Implementation
- Beacon
- Factory (वैकल्पिक / optional)
- Proxy(s)
डिप्लॉयमेंट
ठीक है लेकिन हम इस पूरे सिस्टम को कैसे डिप्लॉय करें? यह उतना डरावना नहीं है जितना लग सकता है।
OpenZeppelin Hardhat और Foundry दोनों के लिए एक Upgrades प्लगइन (plugin) प्रदान करता है। यह लाइब्रेरी को इंस्टॉल करने और beacon कॉन्ट्रैक्ट के पैरामीटर्स के साथ केवल deployBeacon() को कॉल करने जितना ही सरल है। वहाँ से, deployBeaconProxy() को कॉल करके BeaconProxies को डिप्लॉय किया जा सकता है। अपग्रेड करना भी इसी तरह है: नए implementation के पैरामीटर्स के साथ upgradeBeacon() फंक्शन को कॉल किया जाता है।
सिस्टम को मैन्युअली भी डिप्लॉय किया जा सकता है:
- Implementation कॉन्ट्रैक्ट डिप्लॉय करें
- Beacon कॉन्ट्रैक्ट डिप्लॉय करें और कंस्ट्रक्टर में, implementation एड्रेस और उस व्यक्ति का एड्रेस इनपुट करें जिसे implementation एड्रेस को अपग्रेड करने की अनुमति है
- फैक्ट्री कॉन्ट्रैक्ट डिप्लॉय करें
- आवश्यकतानुसार कितने भी प्रॉक्सी डिप्लॉय करने के लिए फैक्ट्री का उपयोग करें

एक रियल-वर्ल्ड उदाहरण (Real World Example)
वास्तविक जीवन में (real life) beacon प्रॉक्सी का उपयोग कब किया जाएगा? मैंने Kwenta के लिए एक beacon प्रॉक्सी बनाया है जो Optimism पर $20M+ TVL के साथ लाइव है।
यह beacon प्रॉक्सी Kwenta vesting पैकेजों के लिए था। “Vesting package” एक स्मार्ट कॉन्ट्रैक्ट है जो प्रोटोकॉल के मुख्य योगदानकर्ताओं (core contributors) और विशेष हितधारकों को धीरे-धीरे टोकन (KWENTA) जारी करता है। प्रत्येक व्यक्ति को एक vesting पैकेज दिया जाता है जो टोकन की मात्रा और अवधि (आमतौर पर 1-4 वर्ष) के हिसाब से अलग-अलग होता है। क्रिप्टो में vesting के बारे में अधिक जानने के लिए यहाँ देखें।
विशेष रूप से beacon प्रॉक्सी ही क्यों?
-
इसे आसानी से अपग्रेड करने योग्य होना चाहिए था। Vesting पैकेजों को अपग्रेड करने योग्य होना ज़रूरी था क्योंकि वे Kwenta स्टेकिंग (staking) सिस्टम पर फंक्शन्स को कॉल करते हैं जो स्वयं भी अपग्रेड करने योग्य है। यदि भविष्य में स्टेकिंग सिस्टम को अपग्रेड किया जाता है, तो vesting पैकेजों पर कार्यक्षमता शायद काम न करे। Vesting पैकेजों को अपग्रेड करने योग्य बनाना उन्हें भविष्य के लिए सुरक्षित (future-proof) बनाता है।
-
प्रत्येक पैकेज में समान vesting लॉजिक (
vest(),stake(), आदि) था लेकिन इनिशियलाइज़्ड पैरामीटर्स (टोकन की मात्रा, vesting की अवधि) अलग-अलग थे। इसके एक हिस्से के लिए vesting पैकेजों को स्टैंडअलोन (standalone) कॉन्ट्रैक्ट या “siloed” बनाने की आवश्यकता थी क्योंकि:a. सरल विकास (Simpler development): प्रति व्यक्ति एक इनिशियलाइज़ेबल (initializable) कॉन्ट्रैक्ट रखना, एक बड़े कॉन्ट्रैक्ट में जटिल मैपिंग्स (mappings) के साथ सभी के अलग-अलग vesting पैकेजों का ट्रैक रखने की तुलना में बहुत सरल था। साथ ही, प्रत्येक पैकेज के लिए KWENTA स्वचालित रूप से पैकेज निर्माण पर स्टेक (stake) हो जाता था, जिसका अर्थ था कि प्रत्येक व्यक्ति रिवॉर्ड्स अर्जित कर रहा था। यदि सभी के पैकेज एक ही कॉन्ट्रैक्ट में एक साथ होते तो रिवॉर्ड्स आपस में मिल जाते और अव्यवस्थित (messy) हो जाते।
b. Vesting पैकेजों का स्वामित्व (Ownership) आसानी से अन्य एड्रेस या मल्टी-सिग (multi-sig) में ट्रांसफर किया जा सकता था।
c. Vesting का मतलब था Kwenta स्टेकिंग कॉन्ट्रैक्ट पर
unstake()को कॉल करना। स्टेकिंग कॉन्ट्रैक्ट में 2 सप्ताह काunstake()कूलडाउन (cooldown) होता है। इसलिए यदि सभी के पैकेज एक कॉन्ट्रैक्ट में होते, और एक व्यक्ति vest करता (और बदले में unstake करता) तो कम से कम 2 सप्ताह तक कोई और vest नहीं कर सकता था। पैकेजों को अलग-अलग कॉन्ट्रैक्ट्स में सलोइंग (siloing) करने से इस बग (bug) से बचा जा सकता है। -
Vesting पैकेजों को 10 से अधिक लोगों का समर्थन करना था। इसका मतलब था 10+ प्रॉक्सी।
एक beacon प्रॉक्सी किसी भी चीज़ से समझौता किए बिना यह सब करने में सक्षम था।
क्लोन आसानी से 10+ इनिशियलाइज़ेबल कॉन्ट्रैक्ट्स डिप्लॉय कर सकते थे लेकिन वे अपग्रेड करने योग्य नहीं होते हैं।
Transparent और UUPS अपग्रेड करने योग्य हैं लेकिन इसके लिए प्रत्येक vesting पैकेज को एक-एक करके अपग्रेड करने की आवश्यकता होगी जो समय लेने वाला होगा और इसमें अधिक गैस (gas) खर्च होगी।
और एक diamond प्रॉक्सी पर विचार किया गया था लेकिन यह इस संरचना के लिए बहुत जटिल था।
Kwenta का FactoryBeacon
एक ऑप्टिमाइज़ेशन (optimization) के रूप में, FactoryBeacon UpgradeableBeacon.sol और Factory कॉन्ट्रैक्ट्स को जोड़ता है। यह संयोजन (combination) सेटअप को सरल बनाता है और सरफेस एरिया (surface area) को कम करता है।

यह संभव है क्योंकि फैक्ट्री को एक स्टैंडअलोन कॉन्ट्रैक्ट होने की आवश्यकता नहीं है: यह केवल कुछ पंक्तियों का कोड है जो एक नया BeaconProxy डिप्लॉय करता है और इसका beacon एड्रेस और इनिशियलाइज़ेशन डेटा सेट करता है।
यहाँ एक संयुक्त (combined) फैक्ट्री और beacon कॉन्ट्रैक्ट का उदाहरण दिया गया है। UpgradeableBeacon को इनहेरिट करके, कॉन्ट्रैक्ट एक नियमित beacon के समान कार्यक्षमता बनाए रखता है, जबकि createBeaconProxy() फंक्शन फैक्ट्री कार्यक्षमता को जोड़ता है। इसके अतिरिक्त, अब beacon एड्रेस को स्टोर करने की कोई आवश्यकता नहीं है, क्योंकि अब address(this) का उपयोग किया जा सकता है।

इसके बावजूद, समग्र “beacon संरचना” (overall beacon structure) अभी भी समान है।
प्रत्येक व्यक्ति अपने BeaconProxy को कॉल करता है जिसमें उनके विशिष्ट vesting पैकेज (vesting की मात्रा, अवधि) के लिए उनका सारा स्टोरेज होता है।
BeaconProxy तब FactoryBeacon से implementation एड्रेस प्राप्त करता है, जिसमें अभी भी एक नियमित beacon के समान कार्य (functions) होते हैं।
FactoryBeacon से implementation एड्रेस प्राप्त करने के बाद, BeaconProxy फिर VestingBaseV2 पर delegatecalls करता है जो केवल implementation है।
ध्यान दें कि केवल adminDAO (एक एडमिन मल्टी-सिग) ही FactoryBeacon को कॉल कर सकता है। एडमिन ही एकमात्र व्यक्ति है जो एक नया vesting पैकेज (BeaconProxy) बना सकता है और प्रॉक्सी को एक नए implementation में अपग्रेड कर सकता है।
निष्कर्ष (Conclusion)
Beacon प्रॉक्सी पैटर्न एक implementation के लिए कई प्रॉक्सी बनाने की अनुमति देता है, जिसमें उन सभी को एक साथ अपग्रेड करने की क्षमता होती है। फैक्ट्री नए प्रॉक्सी डिप्लॉय करती है, जो beacon से प्राप्त एड्रेस पर delegatecall का उपयोग करते हैं। Beacon implementation के लिए सत्य के स्रोत (source of truth) के रूप में कार्य करता है।
यह ध्यान दिया जाना चाहिए कि UUPS या Transparent जैसे अन्य पैटर्न की तुलना में सेटअप के दौरान beacon प्रॉक्सी पैटर्न में अधिक गैस लागत (gas costs) लगती है क्योंकि प्रॉक्सी के अलावा एक फैक्ट्री और एक beacon दोनों को डिप्लॉय किया जाना चाहिए। इसके अतिरिक्त, प्रॉक्सी के प्रत्येक कॉल पर beacon को कॉल करने के लिए एक अतिरिक्त लागत लगती है। यह अतिरिक्त गैस लागत ही मुख्य कमी (drawback) है। यदि आपको कई प्रॉक्सी की आवश्यकता है तो यह आवश्यक रूप से कोई नुकसान नहीं है, क्योंकि यही वह समय है जब beacon प्रॉक्सी पैटर्न सबसे अधिक फायदेमंद होता है। उच्च गैस लागत का यही कारण है कि आप आमतौर पर केवल एक प्रॉक्सी के साथ beacon प्रॉक्सी पैटर्न का उपयोग करते हुए नहीं देखेंगे।
हालाँकि beacon एक साथ कई प्रॉक्सी को अपग्रेड करने की अनुमति देते हैं, लेकिन सेटअप अधिक जटिल और महंगा होता है। इसके लिए अधिक गैस की आवश्यकता होती है और इसमें अतिरिक्त कॉन्ट्रैक्ट स्थापित करना शामिल होता है, जिससे यह विकास (development) और ऑडिटिंग (auditing) के मामले में अधिक महंगा हो जाता है। इसलिए, beacon प्रॉक्सी पैटर्न केवल तभी फायदेमंद है जब आपको बड़ी संख्या में प्रॉक्सी की आवश्यकता हो।
लेखक (Authorship)
यह लेख Andrew Chiaramonte (LinkedIn, Twitter) द्वारा लिखा गया था।
मूल रूप से 20 जुलाई, 2024 को प्रकाशित