Uniswap v4 हुक सुरक्षा विश्लेषण: आर्किटेक्चर, दुर्बलताएँ और श्रेष्ठ अभ्यास

icon MarsBit
साझा करें
AI summary iconसारांश

Uniswap v4 के मुख्य नेटवर्क पर लॉन्च के बाद, Hook मैकेनिज्म DeFi का सबसे अधिक चर्चित नवाचार बन गया है। Base चेन पर memecoin लॉन्च प्लेटफॉर्म Flaunch ने Hook का उपयोग स्थिर प्रीसेल मूल्य और स्वचालित क्लीयरेंस लॉन्च मैकेनिज्म को सक्षम करने के लिए किया है; लिक्विडिटी प्रोटोकॉल Bunni v2 ने Hook का उपयोग प्रोग्रामेबल लिक्विडिटी और पुनर्प्रतिभूति मॉडल बनाने के लिए किया है; इस वर्ष SATO, uPEG (Unipeg), Slonks जैसे Hook-आधारित टोकन्स ने कुछ ही समय में दहाई गुना की वृद्धि की है।

हुक इकोसिस्टम की समृद्धि के दूसरी ओर, हुक के लागू करने की त्रुटियों का उपयोग करके हमले में उल्लेखनीय वृद्धि हुई है। यह लेख Uniswap v4 के हुक मैकेनिज़्म से शुरू होकर, इसके मुख्य कॉल स्टैक का धीरे-धीरे विश्लेषण करता है, ताकि प्रोजेक्ट टीमें इसमें संभावित दुर्बलताओं को समझ सकें।

Uniswap v4 हुक सुरक्षित

1. परिचय

Uniswap v4 का v3 के सापेक्ष सबसे महत्वपूर्ण आर्किटेक्चरल परिवर्तन Hook (हुक) मैकेनिज्म का परिचय है: यह डेवलपर्स को लिक्विडिटी पूल के लाइफसाइकल इवेंट्स पर कस्टम कॉन्ट्रैक्ट्स जोड़ने की अनुमति देता है, जहाँ swap, लिक्विडिटी जोड़ना/घटाना, इनिशियलाइज़ेशन जैसे बिंदुओं पर कोई भी लॉजिक इंजेक्ट किया जा सकता है।

v4 के कुछ प्रमुख परिवर्तन निम्नलिखित हैं:

- सिंगलटन पैटर्न: सभी पूल की स्थिति को एकल PoolManager कॉन्ट्रैक्ट द्वारा केंद्रीय रूप से प्रबंधित किया जाता है, प्रत्येक पूल के लिए अलग-अलग कॉन्ट्रैक्ट तैनात नहीं किए जाते हैं

- फ्लैश अकाउंटिंग: लेनदेन के दौरान मध्यवर्ती शेष बदलाव केवल अस्थायी स्टोरेज में दर्ज किए जाते हैं और केवल लेनदेन के अंत में एकीकृत रूप से सेटल किए जाते हैं

- हुक तंत्र: प्रत्येक पूल एक हुक कॉन्ट्रैक्ट से बंधा जा सकता है, जिसमें PoolManager महत्वपूर्ण बिंदुओं (beforeInitialize, beforeSwap, afterAddLiquidity आदि) पर उस कॉन्ट्रैक्ट को कॉलबैक करता है

- हुक अपरिवर्तनीय है: एक बार पूल इनिशियलाइज़ हो जाने के बाद, बाइंड किया गया हुक पता स्थायी रूप से निर्धारित हो जाता है (पूल से बाइंड किया गया हुक पता बदला नहीं जा सकता, लेकिन हुक कॉन्ट्रैक्ट की अपग्रेड करने की क्षमता इसके वास्तविक कार्यान्वयन पर निर्भर करती है)

चित्र

v3 अवधि में, डेवलपर्स को केवल Uniswap प्रोटोकॉल पर भरोसा करना था; जबकि v4 अवधि में, प्रत्येक पूल की सुरक्षा उससे जुड़े Hook पर निर्भर करती है। Hook ने AMM को एक स्थिर वित्तीय प्राइमिटिव से एक प्रोग्रामेबल वित्तीय बुनियादी ढांचे में विस्तारित कर दिया, लेकिन सुरक्षा मॉडल भी “प्रोटोकॉल-स्तरीय” से “पूल-स्तरीय” तक टुकड़े-टुकड़े हो गया।

2. हुक आर्किटेक्चर

2.1 PoolManager और unlock/callback मॉडल

v4 का कोर कॉन्ट्रैक्ट एकल-उदाहरण PoolManager है। किसी भी पूल की स्थिति में परिवर्तन (स्वैप, लिक्विडिटी जोड़ना या घटाना) के लिए पहले PoolManager.unlock() को कॉल करना आवश्यक है, जिससे एक-बार के कॉलबैक अधिकार की प्राप्ति होती है, और फिर unlockCallback() में विशिष्ट कार्रवाई पूरी की जाती है। पूरी प्रक्रिया समाप्त होने पर, PoolManager जाँच करता है कि लेखा संतुलित है या नहीं:

चित्र

जब NonzeroDeltaCount != 0 हो, तो तुरंत revert कर दें, यह v4 flash accounting का मुख्य प्रतिबंध है। कोई भी Hook निष्पादन के दौरान असंतुलित खाता छोड़ सकता है, लेकिन लेनदेन के अंत से पहले इसे स्वयं settle करना चाहिए, अन्यथा पूरा लेनदेन रद्द हो जाएगा।

प्रत्येक पूल PoolKey संरचना द्वारा अद्वितीय रूप से पहचाना जाता है, जिसमें hooks क्षेत्र शामिल है:

चित्र

PoolId keccak256(PoolKey) द्वारा गणना किया जाता है, इसलिए अलग-अलग hooks पते अलग-अलग पूल उत्पन्न करते हैं। इसका अर्थ यह भी है कि PoolManager कोई जांच नहीं करता कि किसी Hook पते का पहले किसी अन्य पूल के लिए उपयोग किया गया था या नहीं, एक ही Hook स्मार्ट कॉन्ट्रैक्ट को एक से अधिक पूलों द्वारा साथ में बाइंड किया जा सकता है।

चित्र

2.2 हुक अधिकार बिट कोडिंग पते में

v4 का एक अप्रत्याशित डिज़ाइन है: हुक की अनुमतियाँ कॉन्ट्रैक्ट के अंदर किसी चर द्वारा निर्धारित नहीं होती हैं, बल्कि हुक कॉन्ट्रैक्ट के डिप्लॉयमेंट पते द्वारा निर्धारित होती हैं।

PoolManager, Hook पते के निचले 14 बिट्स की जांच करके यह निर्धारित करता है कि क्या किसी जीवनचक्र बिंदु पर इस Hook को कॉल किया जाना चाहिए:

चित्र

उदाहरण के लिए, BEFORE_SWAP_FLAG = 1 << 7। यदि Hook पते का 7वां बिट 1 है, तो PoolManager swap से पहले इस Hook की beforeSwap() को कॉल करेगा; अन्यथा, भले ही Hook कॉन्ट्रैक्ट ने beforeSwap() को लागू किया हो, PoolManager इसे कभी नहीं कॉल करेगा।

इसका अर्थ है कि Hook के डिप्लॉय करते समय CREATE2 + salt के माध्यम से पता की गणना की जानी चाहिए, ताकि एक ऐसा पता बनाया जा सके जिसका निम्न बिट्स लक्ष्य अधिकारों के साथ पूरी तरह मेल खाता हो। Uniswap ने इस उद्देश्य के लिए HookMiner टूल प्रदान किया है:

चित्र

जब अनुमति बिट्स और फ़ंक्शन कार्यान्वयन असंगत होते हैं, तो दो प्रकार की समस्याएँ उत्पन्न होती हैं:

(1) किसी hook फ़ंक्शन को लागू किया गया है, लेकिन पता संबंधित अधिकार बिट्स के लिए एन्कोड नहीं किया गया है — PoolManager कभी भी इस फ़ंक्शन को नहीं बुलाएगा, तार्किक रूप से अनावश्यक

(2) पता में किसी अधिकार बिट को कोड किया गया है, लेकिन hook ने संबंधित फ़ंक्शन को लागू नहीं किया है — PoolManager कॉलबैक के दौरान revert हो सकता है, जिससे DOS हो सकता है या प्रतिक्रिया की जांच विफल हो सकती है, जिससे संबंधित ऑपरेशन नहीं निष्पादित हो सकते।

यह एक साथ हुक अपग्रेड की प्राकृतिक बाधा भी है: यदि हुक को प्रॉक्सी के माध्यम से अपग्रेड किया जा सकता है, तो डिप्लॉयमेंट एड्रेस अपग्रेड के दौरान अपरिवर्तित रहता है, इसलिए अपग्रेड के बाद केवल मौजूदा हुक फ़ंक्शन के कार्यान्वयन को ही संशोधित किया जा सकता है, न कि नए हुक प्रकार जोड़े जा सकते हैं। भविष्य के विस्तार की क्षमता को सुरक्षित रखने के लिए, प्रारंभिक डिप्लॉयमेंट के समय सभी संभावित अधिकार बिट्स को पहले से ही आवंटित करना आवश्यक है।

2.3 BaseHook और एक आमतौर पर नजरअंदाज किए जाने वाले एक्सेस कंट्रोल जाल

Uniswap v4 पेरिफरी द्वारा प्रदान किया गया BaseHook अमूर्त स्मार्ट कॉन्ट्रैक्ट, जिसे डेवलपर्स अपने स्वयं के Hook को लागू करने के लिए विरासत में ले सकते हैं। BaseHook का एक महत्वपूर्ण कार्य unlockCallback() फ़ंक्शन के लिए onlyPoolManager मॉडिफायर प्रदान करना है:

चित्र

लेकिन—यहाँ एक ऐसा डिज़ाइन जाल है जिसे अक्सर नज़रअंदाज़ किया जाता है—प्रारंभिक संस्करण BaseHook ने केवल unlockCallback के लिए onlyPoolManager जोड़ा, अन्य hook कॉलबैक (beforeSwap, afterSwap, beforeAddLiquidity आदि) के लिए कोई सुरक्षा नहीं। इन कार्यों का एक्सेस नियंत्रण Hook विकासक द्वारा स्वयं स्पष्ट रूप से जोड़ा जाना चाहिए।

3. हुक लाइफसाइकल कोड रीड

एक exact-input swap के उदाहरण के साथ, नीचे उपयोगकर्ता द्वारा लेनदेन शुरू करने से लेकर निपटान तक का पूरा कॉल स्टैक दिया गया है।

3.1 पूल इनिशियलाइजेशन और हुक बाइंडिंग

कोई भी PoolManager.initialize() को कॉल करके एक नया पूल बना सकता है:

चित्र

isValidHookAddress केवल पते के अधिकार बिट और शुल्क क्षेत्र की संगतता की जांच करता है, यह यह नहीं जांचता कि Hook पहले से किसी अन्य पूल में उपयोग किया जा रहा है या नहीं, और न ही यह जांचता कि Hook "सहमत" है या नहीं कि यह PoolKey स्वीकार करे। यदि Hook के डिज़ाइन में beforeInitialize में सफेद सूची या एकल पूल बाइंडिंग तर्क शामिल नहीं किया गया है, तो कोई भी व्यक्ति एक नया पूल बना सकता है जिसमें समान Hook का उपयोग किया जाए, लेकिन token pair किसी भी प्रकार का हो सकता है, और Hook के बाद के सभी कॉलबैक को ट्रिगर कर सकता है।

3.2 beforeSwap और BeforeSwapDelta

स्वैप प्रक्रिया का प्रवेश बिंदु PoolManager.swap() है, जो मूल स्वैप तर्क को निष्पादित करने से पहले Hooks.beforeSwap() को कॉल करता है:

चित्र

beforeSwap का रिटर्न मान एक ट्रिपल (bytes4, BeforeSwapDelta, uint24) है:

- bytes4: IHooks.beforeSwap.selector के बराबर होना चाहिए, अन्यथा PoolManager सीधे revert कर देगा

- BeforeSwapDelta: इस swap के दौरान निर्दिष्ट टोकन और अनिर्दिष्ट टोकन के लिए डेल्टा समायोजन

- uint24: डायनामिक LP शुल्क दर कवर मान (केवल तभी लागू होता है जब पूल में डायनामिक शुल्क सक्षम हो)

BeforeSwapDelta int256 का एक बीज है, जिसके उच्च 128 बिट specified token के डेल्टा (अर्थात् उपयोगकर्ता द्वारा निर्दिष्ट मात्रा वाला token) होते हैं, और निम्न 128 बिट unspecified token के डेल्टा होते हैं:

चित्र

ध्यान दें, BeforeSwapDelta का अर्थ है कि Hook द्वारा शुल्क वसूले जाने पर धनात्मक मान लौटाया जाना चाहिए और Hook द्वारा टोकन वापस दिए जाने पर ऋणात्मक मान लौटाया जाना चाहिए। डेवलपर्स आसानी से संकेत गलत कर सकते हैं; साथ ही, specified और unspecified का संबंध params.zeroForOne और amountSpecified के चिह्न पर निर्भर करता है, जिसका सही तरीके से लिखना न होने पर token का गलत स्थान पर होना संभव है।

PoolManager द्वारा beforeSwap द्वारा लौटाए गए specifiedDelta को amountToSwap पर सीधे जोड़ दिया जाता है:

चित्र

इस पंक्ति में एक महत्वपूर्ण अर्थ निहित है: Hook swap राशि को रोक सकता है। जब hookDeltaSpecified, -params.amountSpecified के बराबर होता है, तो amountToSwap सीधे शून्य हो जाता है, जिससे Hook पूरी तरह से इस swap को नियंत्रित कर लेता है—इसे Async Hook या Custom Curve Hook कहा जाता है।

Async Hook v4 में सबसे अधिक जोखिम वाला डिजाइन पैटर्न है: यह मूल रूप से Uniswap के swap लॉजिक को Hook के अपने लॉजिक से बदल देता है। यदि Hook में कोई दुर्बलता है या यह स्वयं ही दुष्ट है, तो उपयोगकर्ता की धनराशि Uniswap के मूल मूल्य निर्धारण लॉजिक से अब बंधी नहीं होगी, बल्कि मुख्य रूप से Hook के स्वयं के कार्यान्वयन की सही प्रक्रिया पर निर्भर करेगी।

3.3 डेल्टा सेटलमेंट और NonzeroDeltaCount

beforeSwap और afterSwap द्वारा लौटाया गया डेल्टा तुरंत ट्रांसफर नहीं करता, बल्कि PoolManager के आंतरिक लेज़र में रिकॉर्ड किया जाता है:

चित्र

जब किसी टोकन की संचयी डेल्टा शून्य से गैर-शून्य हो जाती है, तो NonzeroDeltaCount बढ़ जाता है; जब यह फिर से शून्य हो जाता है, तो यह घट जाता है। जैसा कि 2.1 में बताया गया है, unlock() के समाप्त होने पर यदि NonzeroDeltaCount != 0 है, तो पूरी लेनदेन revert हो जाती है।

Hook, settle() (PoolManager को ट्रांसफर करके) और take() (PoolManager से निकालकर) दो क्रियाओं के माध्यम से अपना डेल्टा संतुलित करता है:

चित्र

इस तंत्र द्वारा प्रदान की गई सुरक्षा अर्थव्यवस्था स्पष्ट है: सभी को अंततः अपने खाते समायोजित करने होंगे। लेकिन यह केवल “खाता संरक्षण” की गारंटी देता है, “खाता सही है” की नहीं। यदि Hook beforeSwap में एक दुरुपयोगपूर्ण रूप से निर्मित डेल्टा लौटाता है, तो PoolManager उस डेल्टा के अनुसार विश्वासपूर्वक लेखा करेगा, जब तक कि अंततः settle द्वारा समायोजित न हो जाए—यहां तक कि यदि इसका अर्थ है कि Hook बिजनेस स्टेट को झूठा बनाकर सिस्टम को यह गलत धारणा दे सकता है कि हमलावर के पास कुछ संपत्ति के हिस्से हैं, जबकि PoolManager इस बिजनेस-लेवल की त्रुटि को पहचान नहीं सकता।

पहले कॉर्क प्रोटोकॉल की सुरक्षा घटना इसलिए घटी क्योंकि उसका हुक दुर्बल था, और इस पर हमले से पहले चार ऑडिट कंपनियों ने ऑडिट किया था। घटना के बाद हमने समीक्षा की कि:

चार में से तीन ऑडिट में CorkHook कॉन्ट्रैक्ट का स्कोप शामिल नहीं है

- केवल एक ऑडिटर ने CorkHook की ऑडिट की, जिसने कुछ कोड समस्याओं की पहचान की और सुधार के सुझाव दिए, लेकिन एक्सेस कंट्रोल समस्याओं को पूरी तरह से कवर नहीं किया।

एक अन्य ऑडिटर ने अपनी रिपोर्ट में स्पष्ट रूप से सुझाव दिया: "एक दिलचस्प अनुगामी एंगेजमेंट यह होगा कि इस एंगेजमेंट के दायरे के भीतर सत्यापित विभिन्न घटकों द्वारा कॉल किए जा रहे CorkHook फ़ंक्शन के अपरिवर्तनीयता सिद्ध किए जाएं।" इस सुझाव की पश्चात् समीक्षा के दृष्टिकोण से अत्यधिक प्रासंगिकता है।

यह v4 Hook युग के लिए एक नया ऑडिट अंधबिंदु उजागर करता है: प्रोटोकॉल की जटिलता में विस्फोटक वृद्धि के कारण, स्कोप की परिभाषा स्वयं एक सुरक्षा निर्णय बन गई है। Hook और प्रोटोकॉल के अन्य स्मार्ट कॉन्ट्रैक्ट्स के बीच इंटरैक्शन चेन बहुत लंबी होती है; केवल Hook कॉन्ट्रैक्ट की समीक्षा करने से क्रॉस-कॉन्ट्रैक्ट संयोजन समस्याएँ नहीं मिलतीं; विपरीत रूप से, यदि आप परिधि कॉन्ट्रैक्ट्स की समीक्षा करते हैं और Hook को स्कोप से बाहर रखते हैं, तो v4 युग का सबसे बड़ा हमला सतह लुप्त हो जाता है।

4. प्रतिबिंब

प्रोटोकॉल मैकेनिज्म और Cork हमले की समीक्षा को समानांतर रूप से देखने से, v4 Hook सुरक्षा मॉडल के कुछ मुख्य बिंदुओं को सारांशित किया जा सकता है:

(1) यदि Hook कॉलबैक फ़ंक्शन PoolManager द्वारा प्रदान किए गए कॉल कंटेक्स्ट पर निर्भर करता है, तो इसे स्पष्ट रूप से केवल PoolManager द्वारा ही कॉल किए जाने के लिए सीमित किया जाना चाहिए। BaseHook इसे डेवलपर के लिए नहीं करेगा, यह v4 और सामान्य स्मार्ट कॉन्ट्रैक्ट ऑडिट अनुभव के बीच सबसे आसानी से टकराने वाला डिज़ाइन जाल है।

(2) हुक और पूल के बाइंडिंग संबंध को PoolManager द्वारा प्रतिबंधित नहीं किया जाता है। डेवलपर्स को beforeInitialize में पूल व्हाइटलिस्ट या सिंगल पूल बाइंडिंग अपने आप लागू करना होगा।

(3) हुक एड्रेस के परमिशन बिट्स को फंक्शन इम्प्लीमेंटेशन के साथ सख्ती से मेल खाना चाहिए। गणना किए गए एड्रेस में भविष्य में संभावित विस्तार के लिए सभी परमिशन बिट्स पहले से शामिल होने चाहिए।

(4) असिंक / कस्टम कर्व हुक मूल रूप से पूरी तरह से कस्टमाइज़ड स्वैप इम्प्लीमेंटेशन है। इसमें कोई यूनिस्वैप प्रोटोकॉल स्तर की सुरक्षा नहीं है, और इसे "पूर्णतः स्वायत्त वित्तीय अनुबंध" मानक के अनुसार ऑडिट किया जाना चाहिए।

(5) डेल्टा अकाउंटिंग का “संरक्षण” “सही” के बराबर नहीं है। NonzeroDeltaCount == 0 केवल यह गारंटी देता है कि लेजर अंततः संतुलित होगा, लेकिन यह यह नहीं गारंटी देता कि लेजर की सामग्री को दुरुपयोगपूर्ण ढंग से नियंत्रित नहीं किया गया है।

(6) क्रॉस-मार्केट टोकन प्रकार का भ्रम v4 युग का एक नया हमला का क्षेत्र है। जब प्रोटोकॉल उपयोगकर्ताओं को बाजार बनाने की अनुमति देता है, तो टोकन की अर्थशास्त्रीय जांच आवश्यक है, केवल इंटरफेस जांच पर निर्भर नहीं होना चाहिए।

प्रत्येक Hook एक स्वतंत्र विश्वास क्षेत्र है, और प्रत्येक पूल की सुरक्षा उसके से बंधे Hook द्वारा निर्धारित होती है। इसलिए Hook सुरक्षा ऑडिट की जटिलता अब “एक कोड की समीक्षा” नहीं, बल्कि “एक पूर्ण उप-प्रोटोकॉल की समीक्षा” है—यह परिवर्तन प्रोजेक्ट टीम और ऑडिटर दोनों के लिए विधि में उन्नति का अर्थ है।

देखें मूल पाठ

डिस्क्लेमर: इस पेज पर दी गई जानकारी थर्ड पार्टीज़ से प्राप्त की गई हो सकती है और यह जरूरी नहीं कि KuCoin के विचारों या राय को दर्शाती हो। यह सामग्री केवल सामान्य सूचनात्मक उद्देश्यों के लिए प्रदान की गई है, किसी भी प्रकार के प्रस्तुतीकरण या वारंटी के बिना, न ही इसे वित्तीय या निवेश सलाह के रूप में माना जाएगा। KuCoin किसी भी त्रुटि या चूक के लिए या इस जानकारी के इस्तेमाल से होने वाले किसी भी नतीजे के लिए उत्तरदायी नहीं होगा। डिजिटल संपत्तियों में निवेश जोखिम भरा हो सकता है। कृपया अपनी वित्तीय परिस्थितियों के आधार पर किसी प्रोडक्ट के जोखिमों और अपनी जोखिम सहनशीलता का सावधानीपूर्वक मूल्यांकन करें। अधिक जानकारी के लिए, कृपया हमारे उपयोग के नियम और जोखिम प्रकटीकरण देखें।