इस लेख के पहले भाग में, मैंने एक ऐसे मामले का वर्णन किया जहाँ स्वैपिंग सेवा rabbit.io क्लाइंट को थोड़ी मात्रा में SOL भेजने की कोशिश कर रही थी, लेकिन लेनदेन बार‑बार अस्वीकृत हो रहा था - हालांकि, सोलाना ब्लॉकचेन के सभी ज्ञात नियमों के अनुसार, सब कुछ पूरी तरह वैध प्रतीत हो रहा था।
उस पहले भाग में उन परिस्थितियों को भी कवर किया गया जहाँ तकनीकी रूप से सही लेनदेन को भी XRP Ledger, Stellar, और Lightning Network (Bitcoin का लेयर 2) जैसे नेटवर्क में अस्वीकार किया जा सकता है। मैंने USDC स्मार्ट कॉन्ट्रैक्ट में ब्लैकलिस्ट के एक इम्प्लीमेंटेशन विवरण को भी समझाया था, जो ऐसे मामलों में USDC लेनदेन को आकस्मिक रूप से विफल कर सकता है, भले ही प्रेषक की तरफ कुछ भी गलत न दिखे।
यदि आपने पार्ट I मिस किया है, तो आप इसे यहाँ पढ़ सकते हैं।
आज मैं कई समान उदाहरणों को अन्य नेटवर्क और टोकन के संदर्भ में देखना चाहता हूँ। हर उदाहरण में, पहली नजर में सब कुछ सही दिख सकता है — पर लेनदेन फिर भी विफल हो जाता है।
यह मामला विशेष रूप से DeFi प्रोटोकॉल के डेवलपर्स और ऑपरेटरों के लिए प्रासंगिक है। फिर भी, सामान्य उपयोगकर्ता भी इसके परिणामों का अनुभव कर सकते हैं।
कल्पना कीजिए। आप किसी प्रोटोकॉल में USDC, DAI और USDT जमा करने की कोशिश कर रहे हैं। USDC और DAI के साथ जमा ठीक से हो जाते हैं, लेकिन USDT ट्रांसफर रिवर्ट हो जाता है। पता सही है, नेटवर्क सही है, और गैस पर्याप्त है। कारण क्या है?
कारण यह है कि Ethereum पर USDT पूरी तरह से ERC-20 मानक के अनुरूप नहीं है। मानक में transfer और transferFrom फ़ंक्शनों को एक बूलियन मान लौटाना आवश्यक होता है: सफल होने पर true और विफल होने पर false. USDT कुछ भी वापस नहीं करता।
यदि कोई स्मार्ट कॉन्ट्रैक्ट सख्ती से ERC-20 मानक के अनुसार लिखा गया है और transfer कॉल के जवाब में बूलियन मान प्राप्त करने की उम्मीद करता है, जबकि USDT कुछ नहीं लौटाता, तो EVM वर्चुअल मशीन (Solidity संस्करण 0.4.22 और उसके बाद) इसे एक त्रुटि के रूप में व्याख्यायित करती है और ट्रांसफर को रिवर्ट कर देती है। तकनीकी रूप से लेनदेन सफल हो सकता था, लेकिन उसे जबरदस्ती रोलबैक कर दिया जाता है। और प्रेषक को नेटवर्क या स्मार्ट कॉन्ट्रैक्ट की तरफ से यह स्पष्ट संकेत नहीं मिलता कि वास्तव में क्या गलत हुआ।
यह उदाहरण rabbit.io पर किए गए स्वैप्स से संबंधित नहीं है। हमारी प्रणाली सबसे सरल और सबसे भरोसेमंद तरीके से संगठित है: आपको एक पता मिलता है जहाँ आप मैन्युअली अपने टोकन भेजते हैं, और बदले में आपको हमसे इच्छित टोकन मिलते हैं। DeFi स्मार्ट कॉन्ट्रैक्ट शामिल नहीं होते।
फिर भी, उन पाठकों के लिए जो केवल rabbit.io पर स्वैप नहीं करते बल्कि सक्रिय रूप से DeFi के साथ इंटरैक्ट करते हैं — जिनमें डेवलपर्स भी शामिल हैं — मैं एक सरल समाधान सुझा सकता हूँ। OpenZeppelin की SafeERC20 लाइब्रेरी का उपयोग करें, जो गैर-मानक टोकन्स को सही तरीके से हैंडल करती है।
ज्यादातर पेशेवर रूप से लिखे गए DeFi प्रोटोकॉल यह पहले से करते हैं। हालांकि, पुराने या अनप्रोफेशनल स्मार्ट कॉन्ट्रैक्ट USDT के साथ इंटरैक्ट करते समय अभी भी टूटते हैं। यह समस्या इतनी व्यापक है कि इसे ज्ञात टोकन विचित्रताओं के weird-erc20 डेटाबेस में शामिल किया गया है, जहाँ आप इसी प्रकार के व्यवहार वाले अन्य टोकन्स भी पा सकते हैं।
Ethereum पर USDT में एक और विशिष्टता है जो नियमित रूप से स्मार्ट कॉन्ट्रैक्ट्स के साथ लेनदेन को विफल कर देती है।
ERC-20 मानक में, यदि आप किसी स्मार्ट कॉन्ट्रैक्ट को अपने टोकन खर्च करने की अनुमति देना चाहते हैं, तो आप फ़ंक्शन approve(spender, amount) कॉल करते हैं। उदाहरण के लिए, यदि आप अनुमति (allowance) को 100 से बढ़ाकर 200 USDC करना चाहते हैं, तो आप बस approve(spender, 200) कॉल करते हैं।
USDT अलग ढंग से काम करता है। इसके कोड में स्पष्ट रूप से कहा गया है कि यदि प्राप्तकर्ता पते के पास पहले से नॉन-जीरो अनुमति है, तो उसे सीधे नया नॉन-जीरो मान सेट करने की अनुमति नहीं है। एक ऐसा लेनदेन जो किसी अन्य टोकन के साथ पूरी तरह वैध होगा, USDT के साथ अस्वीकार कर दिया जाता है।
यह व्यवहार अनुमतियों से संबंधित डबल-स्पेंड अटैक के खिलाफ सुरक्षा के रूप में पेश किया गया था। डेवलपर्स का डर था कि कोई अटैकर तुरंत पुराने और नए दोनों अनुमतियों को खर्च कर सकता है।
इसलिए USDT अनुमति बदलने का अनिवार्य पैटर्न निम्नलिखित है:
approve(spender, 0) कॉल करके अनुमति रीसेट करेंapprove(spender, new_value) कॉल करेंडेसेंट्रलाइज़्ड एप्लिकेशन के उपयोगकर्ताओं के लिए यह भ्रमित करने वाला हो सकता है। उपयोगकर्ता ने पहले एप्लिकेशन को अनुमति दी थी, अब वह अलग अनुमति सेट करना चाहता है, लेनदेन साइन करता है — पर कुछ भी बदलता नहीं है और कोई स्पष्ट व्याख्या नहीं मिलती।
यह उदाहरण भी rabbit.io पर किए गए स्वैप्स से संबंधित नहीं है। हमारे प्लेटफ़ॉर्म पर ऐसे अस्वीकृत लेनदेन नहीं हो सकते क्योंकि rabbit.io वॉलेट कनेक्ट करने की आवश्यकता नहीं रखता और न ही टोकन खर्च करने की अनुमति मांगता है।
हालाँकि, यदि किसी dApp में आपका approve ट्रांजैक्शन USDT के साथ विफल होता है, तो समाधान आमतौर पर सरल है। वर्तमान अनुमति स्तर जाँचें। यदि वह नॉन-जीरो है, तो पहले उसे शून्य पर रीसेट करें और तभी नया मान सेट करें।
बिटकॉइन नेटवर्क में एक अवधारणा है जिसे डस्ट कहा जाता है। यह उस ट्रांजैक्शन आउटपुट को संदर्भित करता है जिसकी वैल्यू बाद में खर्च करने के लिए आवश्यक फीस से छोटी होती है। दूसरे शब्दों में, सिक्के तकनीकी रूप से आपके वॉलेट में मौजूद होते हैं, लेकिन उन्हें भेजने के लिए आवश्यक फीस उन सिक्कों से अधिक होगी।
यह समझना महत्वपूर्ण है कि सर्वसम्मति नियम (consensus rules) और नोड नीति (node policy) के बीच एक मौलिक अंतर है, जिसे अक्सर भ्रमित किया जाता है।
एक ऐसा लेनदेन जिसके आउटपुट डस्ट लिमिट से छोटे हैं, तकनीकी रूप से बिटकॉइन सर्वसम्मति नियमों के अनुसार वैध हो सकता है। लेकिन अधिकांश नोड डिफ़ॉल्ट रूप से ऐसे लेनदेन को रिले करने से इनकार कर देंगे, और अधिकांश माइनर्स इसे किसी ब्लॉक में शामिल करने से मना कर देंगे।
कारण सरल है: बेहद छोटे सिक्कों को स्टोर करना डेटाबेस पर बोझ डालता है बिना किसी वास्तविक आर्थिक लाभ के।
डस्ट लिमिट एड्रेस के प्रकार और न्यूनतम रिले फीस पर निर्भर करती है। ऐतिहासिक रूप से डस्ट लिमिट को 546 सतोशी माना जाता है। अगर न्यूनतम फीस रेट 1 sat/vByte है तो छोटे आउटपुट वाले लेनदेन भेजे जा रहे अमाउंट से ज़्यादा फीस लेते, इसलिए वे अनुकूल नहीं होते। पर यह केवल उन लेगेसी एड्रेस (जो "1" से शुरू होते हैं) पर लागू होता है।
आधुनिक एड्रेस प्रकार ब्लॉकचेन में कम जगह घेरते हैं, इसलिए उनकी डस्ट लिमिट कम हो सकती है। उदाहरण के लिए, सामान्य bc1q... एड्रेस के लिए 1 sat/vByte की फीस रेट पर डस्ट लिमिट 294 सतोशी है, और वर्तमान में लागू न्यूनतम रिले फीस (0.1 sat/vByte) के साथ डस्ट लिमिट दस गुना कम हो जाती है।

कल्पना कीजिए निम्न स्थिति।
आपके पास 100,000 सतोशी (0.001 BTC) हैं। आप किसी को 99,000 सतोशी भेजना चाहते हैं। आप एक ट्रांजैक्शन बनाते हैं, और नेटवर्क फीस 980 सतोशी है। बची हुई 20 सतोशी आपको चेंज के रूप में वापस मिलने चाहिए।
लेकिन ऐसा नहीं होगा। आप अपना चेंज नहीं पाएंगे, और मुख्य भुगतान प्राप्तकर्ता तक भी नहीं पहुंचेगा। रिले नोड्स का नेटवर्क चुपचाप उस ट्रांजैक्शन को अस्वीकार कर देगा क्योंकि उसके एक आउटपुट की वैल्यू डस्ट लिमिट से नीचे है।
इसका एक संबंधित समस्या भी है: बाद में डस्ट को खर्च करना। यदि आप कम फीस के समय में कई आउटपुट 294 सतोशी से छोटे प्राप्त करते हैं, और बाद में फीस बढ़ जाती है, तो उन सिक्कों को खर्च करने का कोई भी प्रयास इतना महंगा हो सकता है कि ट्रांसफर की गई राशि आवश्यक फीस को भी पूरा न कर पाए।
इसलिए, जब अन्य क्रिप्टो संपत्तियों को बिटकॉइन में एक्सचेंज करें, तो सुनिश्चित करें कि बनाए जा रहे आउटपुट डस्ट लिमिट से अधिक हों। Rabbit.io वर्तमान डस्ट लिमिट से कई गुना बड़े अमाउंट में स्वैप की अनुमति देता है। हालांकि, यदि नेटवर्क फीस बढ़ती है, तो ऐसे छोटे अमाउंट्स को आगे भेजना मुश्किल हो सकता है।
Ethereum और किसी भी EVM‑संगत ब्लॉकचेन (जैसे BSC, HyperEVM आदि) में, किसी विशेष पते से भेजे गए हर ट्रांजैक्शन का एक क्रमिक नंबर होता है जिसे nonce कहा जाता है।
नेटवर्क ट्रांजैक्शनों को सख्ती से क्रम में प्रोसेस करता है: पहले nonce = 0 वाला, फिर nonce = 1, फिर 2, और इसी तरह। किसी संख्या को स्किप करना असंभव है।
यदि कोई ट्रांजैक्शन बहुत कम गैस फीस के कारण मेमपूल में अटक जाता है, तो उसी पते से उच्च nonce वाले सभी बाद के ट्रांजैक्शन भी पेंडिंग रहेंगे, भले ही उनकी फीस सामान्य हों।
यहाँ एक बहुत ही वास्तविक परिदृश्य है। कुछ हफ्ते पहले आपने एक कम गैस फीस वाला ट्रांजैक्शन भेजा था। वह अटक गया। आप उसे भूल गए। अब आप नया ट्रांजैक्शन भेजने की कोशिश करते हैं। आप सही पता देते हैं और उचित फीस सेट करते हैं, पर ट्रांजैक्शन प्रोसेस नहीं हो रहा।
समस्या वर्तमान ट्रांजैक्शन में नहीं है, बल्कि पुराने पेंडिंग ट्रांजैक्शन में है।
समाधान यह है कि उसी पुराने nonce के साथ एक ट्रांजैक्शन भेजें लेकिन उच्च गैस फीस के साथ। इससे या तो मूल ट्रांजैक्शन तेज़ होगा (speed up) या वह कैंसिल हो जाएगा। आखिरी स्थिति तब होती है जब आप उसी nonce पर अपने ही पते को ट्रांसफर भेजते हैं साथ ही उच्च गैस फीस रखते हैं।
हालाँकि, ध्यान रखें कि सभी वॉलेट्स उपयोगकर्ताओं को nonce वैल्यू नियंत्रित करने की अनुमति नहीं देते। उदाहरण के लिए, लोकप्रिय वॉलेट्स जैसे Trust Wallet और Exodus यह फ़ंक्शन प्रदान नहीं करते। वहीं, MetaMask — जिसे कई लोग पुराना और असुविधाजनक मानते हैं — वास्तव में यह अनुमति देता है।
TRON नेटवर्क का रिसोर्स मॉडल असामान्य है। एकल ट्रांजैक्शन फीस के बजाय, ट्रांजैक्शन्स दो प्रकार के रिसोर्सेस का उपभोग करते हैं:
एनर्जी TRX को फ्रीज़ करके प्राप्त की जा सकती है। यदि ऐसा नहीं किया गया है, तो नेटवर्क लागत को कवर करने के लिए स्वचालित रूप से TRX जला देता है।
और यहीं एक अप्रत्याशित प्राइसिंग समस्या सामने आती है:
यदि प्रेषक के पास फीस के लिए 15 TRX उपलब्ध हैं लेकिन ट्रांसफर एक नए पते पर जा रहा है, तो ट्रांजैक्शन OUT OF ENERGY त्रुटि के साथ विफल हो सकता है। इस प्रयास में खर्च हुआ TRX वापस नहीं मिलता।
दूसरे शब्दों में, स्थिति फिर से उन उदाहरणों से मिलती‑जुलती है: पता सही है, नेटवर्क सही है, प्रेषक के पास USDT है, TRX मौजूद था — फिर भी लेनदेन विफल हो जाता है।
निष्कर्ष सरल है: USDT TRC-20 के साथ स्थिर काम के लिए, बैलेंस पर संभव लेनदेन लागत को कवर करने हेतु कम से कम 27 TRX रखना सलाहकार है।
SOL ट्रांसफर के असफल अनुभव ने मुझे एक मूल्यवान सबक सिखाया। न कि इस अर्थ में कि मुझे ब्लॉकचेन समझने में कुछ कमी थी, बल्कि इस अर्थ में कि हर ब्लॉकचेन अपना एक अलग पारिस्थितिकी तंत्र है जिनके छिपे नियम होते हैं, जो हमेशा स्पष्ट रूप से दस्तावेजीकृत नहीं होते और कभी‑कभी केवल असामान्य परिस्थितियों में ही प्रकट होते हैं।
हर भ्रमित करने वाली विफलता निराशा का कारण नहीं है, बल्कि कुछ नया सीखने का अवसर है। और जितना अधिक नया मैं सीखता हूँ, उतना ही रोचक मेरे लिए क्रिप्टोकरेंसी के साथ काम करना होता है।
यदि आप भी ऐसा महसूस करते हैं, तो असामान्य मामलों का दस्तावेज़ीकरण करें और अपने निष्कर्ष साझा करें। जब व्यावहारिक अनुभव आधिकारिक दस्तावेज़ीकरण से तेज़ी से फैलता है, तब क्रिप्टो इंडस्ट्री अधिक भरोसेमंद बनती है।