फ़ॉलबैक-एक्सटेंशन पैटर्न 24 KB की स्मार्ट कॉन्ट्रैक्ट आकार सीमा (size limit) को पार करने का एक सरल तरीका है।
मान लीजिए कि हमारे primary कॉन्ट्रैक्ट में foo() और bar() फ़ंक्शन्स हैं और हम baz() को जोड़ना चाहते हैं, लेकिन जगह की कमी के कारण ऐसा नहीं कर सकते।
हम अपने primary स्मार्ट कॉन्ट्रैक्ट में एक फ़ॉलबैक (fallback) फ़ंक्शन जोड़ते हैं जो अननोन (unknown) फ़ंक्शन कॉल्स को एक extension कॉन्ट्रैक्ट पर डेलिगेट (delegate) करता है, ठीक उसी तरह जैसे एक प्रॉक्सी काम करता है।
हम baz() को extension कॉन्ट्रैक्ट में रखते हैं। जब हम मुख्य कॉन्ट्रैक्ट पर baz() को कॉल करते हैं, तो यह primary कॉन्ट्रैक्ट के किसी भी फ़ंक्शन सिलेक्टर्स से मेल नहीं खाएगा, और इस तरह फ़ॉलबैक फ़ंक्शन ट्रिगर हो जाएगा। फिर, extension कॉन्ट्रैक्ट में baz() को delegatecalled किया जाएगा।
एक समान स्टोरेज लेआउट (storage layout) सुनिश्चित करना
इस पैटर्न के काम करने के लिए, प्राइमरी कॉन्ट्रैक्ट और एक्सटेंशन कॉन्ट्रैक्ट दोनों में एक समान स्टोरेज लेआउट होना आवश्यक है। इसे पूरा करने का एक आसान तरीका यह है कि सभी स्टोरेज वेरिएबल्स को (बिना किसी अपवाद के!) एक ही कॉन्ट्रैक्ट में रखा जाए। फिर प्राइमरी कॉन्ट्रैक्ट और एक्सटेंशन कॉन्ट्रैक्ट दोनों को उससे इनहेरिट (inherit) किया जाता है। यहाँ एक उदाहरण दिया गया है:

एक्सटेंशन बदलना
ऊपर दिए गए उदाहरण में, एक्सटेंशन कॉन्ट्रैक्ट का एड्रेस एक इम्यूटेबल (immutable) वेरिएबल में स्टोर किया गया है। हम स्टोरेज कॉन्ट्रैक्ट में एक अतिरिक्त स्टोरेज वेरिएबल जोड़ सकते हैं जो एक्सटेंशन के एड्रेस को होल्ड करता है, फिर जब हम कॉन्ट्रैक्ट की कुछ कार्यक्षमता (functionality) को बदलना चाहते हैं तो एक्सटेंशन एड्रेस को अपडेट कर सकते हैं।
यह तरीका अनुशंसित (recommended) नहीं है — यदि अपग्रेडेबिलिटी (upgradeability) की आवश्यकता है, तो किसी स्थापित प्रॉक्सी पैटर्न का उपयोग करना बेहतर है। इसके अलावा, स्टोरेज से उस एक्सटेंशन एड्रेस वेरिएबल को पढ़ने में अतिरिक्त 2,100 गैस (gas) का खर्च आएगा।
फ़ंक्शन सिलेक्टर कॉलिजन (function selector collisions) से बचने के लिए सावधानी बरतनी चाहिए
इस बात की लगभग 4 मिलियन में 1 संभावना है कि दो रैंडम फ़ंक्शन्स का सिलेक्टर समान होगा। हालाँकि, बर्थडे पैराडॉक्स (birthday paradox) के कारण, यह संभावना तेज़ी से बढ़ जाती है जब हमारे पास n फ़ंक्शन सिलेक्टर्स होते हैं और अवांछित (unwanted) व्यवहार पैदा करने के लिए केवल एक कॉलिजन (collision) की आवश्यकता होती है। इसके लिए कोई टूल्स नहीं हैं, डेवलपर को मैन्युअली फ़ंक्शन सिलेक्टर्स की जांच करनी होगी।
गैस संबंधी विचार (Gas Considerations)
एक्सटेंशन स्वयं इस पैटर्न का पालन कर सकता है और इसे किसी अन्य डेलिगेट (delegate) को भेज सकता है। वास्तव में, सैद्धांतिक रूप से इस बात की कोई सीमा नहीं है कि हम ऐसा कितनी बार कर सकते हैं।
हालाँकि, प्रत्येक “हॉप (hop)” एक अतिरिक्त 2,600 गैस जोड़ता है (एक नए एड्रेस पर CALL या DELEGATECALL जारी करने के लिए आवश्यक न्यूनतम गैस), इसलिए यदि चेन लंबी है तो लागत (cost) काफी अधिक हो सकती है।
चूँकि एक्सटेंशन में फ़ंक्शन्स की लागत अतिरिक्त 2,600 गैस होती है, इसलिए हम शायद ही कभी उपयोग किए जाने वाले फ़ंक्शन्स को एक्सटेंशन में रखना चाहते हैं, या ऐसे फ़ंक्शन्स जिन्हें मुख्य रूप से ऑफ-चेन (off-chain) से कॉल किया जाना है जहाँ गैस कोई मायने नहीं रखती है।
इस पैटर्न के साथ EIP 2930 का उपयोग करें
इस पैटर्न के साथ एक्सेस लिस्ट ट्रांज़ेक्शन्स का उपयोग करने से एक्सटेंशन में फ़ंक्शन्स को कॉल करते समय 100 गैस की बचत होगी। सामान्य तौर पर, यदि किसी Ethereum ट्रांज़ेक्शन में क्रॉस-कॉन्ट्रैक्ट कॉल या delegatecall शामिल है, तो एक्सेस लिस्ट ट्रांज़ेक्शन का उपयोग किया जाना चाहिए।
अपग्रेडेबल प्रॉक्सी (upgradeable proxies) के लिए इम्प्लीमेंटेशन कॉन्ट्रैक्ट (implementation contract) के रूप में फ़ॉलबैक-एक्सटेंशन का उपयोग करना
इस पैटर्न का उपयोग रेगुलर प्रॉक्सी के साथ किया जा सकता है। यानी, एक प्रॉक्सी कॉन्ट्रैक्ट एक इम्प्लीमेंटेशन कॉन्ट्रैक्ट को डेलिगेट कर सकता है जो फिर एक एक्सटेंशन को डेलिगेट करता है। ध्यान रखें कि अपग्रेड के लिए टूलिंग (जैसे Openzeppelin अपग्रेड टूल्स) एक्सटेंशन फ़ॉलबैक पैटर्न के साथ काम करने के लिए डिज़ाइन नहीं किए गए हैं और हो सकता है कि वे अपग्रेड से जुड़ी समस्याओं को न पकड़ पाएं।
RareSkills के साथ और जानें
अधिक जानने के लिए कृपया हमारा Solidity Bootcamp देखें।
मूल रूप से 28 दिसंबर, 2023 को प्रकाशित