Compound V3 contract एक rebasing ERC-20 token की तरह व्यवहार करता है। एक rebasing token वह token होता है जिसकी सप्लाई fixed होने के बजाय algorithmically adjust की जाती है। यहाँ “token” positive USDC balances की present value को दर्शाता है। अर्थात्, lenders अपने principal की present value को अन्य addresses पर ऐसे ट्रांसफर कर सकते हैं जैसे कि यह एक ERC-20 token हो। चूँकि interest accrual (ब्याज जमा होने) के कारण principal value आम तौर पर बढ़ रही होती है, इसलिए यह ERC-20 token समय के साथ ऊपर की ओर rebasing कर रहा है।
Compound V3 lending pool के “shares” को ट्रैक करने के लिए किसी token vault standard (जैसे ERC-4626) का उपयोग नहीं करता है।
जैसा कि हमने principal और present value की अपनी चर्चा में बताया था, हो सकता है कि एक user ने 100 USDC deposit किया हो, लेकिन accrued interest के कारण उसके पास 110 USDC का credit हो — यह 110 ही present value है। Compound V3 की ERC-20 functionality अकाउंट की इसी unit को manage करती है।
आवश्यक शर्तें (Prerequisites)
Users को interest indexes और Compound V3 के present value and principal value की धारणा से परिचित होना चाहिए। इस लेख में Compound V3 और Comet शब्दों का उपयोग एक-दूसरे के स्थान पर किया गया है क्योंकि Comet उस primary smart contract का नाम है जिसमें वे functions मौजूद हैं जिनकी हम यहाँ चर्चा कर रहे हैं।
इस लेख की संरचना
प्रत्येक heading एक ऐसे ERC-20 function पर चर्चा करेगी जिसे Compound V3 implement करता है, और यह उस function को कैसे implement करता है। कुछ functions ERC-20 standard का हिस्सा नहीं हैं, लेकिन इस चर्चा के लिए प्रासंगिक हैं।
totalSupply और totalBorrow (Comet.sol)
जैसा कि नाम से पता चलता है, totalBorrow उधार ली गई USDC की कुल राशि है। अर्थात्, यह debt की present value है। हम इसकी पुष्टि उस चीज़ से कर सकते हैं जो contract return करता है और जो हम Compound प्लेटफॉर्म पर देखते हैं। यह केवल वह USDC की राशि नहीं है जिसे borrowers ने प्लेटफॉर्म से निकाला है — इसमें उधार ली गई USDC पर अर्जित ब्याज भी शामिल है।
नीचे हम Compound V3 UI का एक स्क्रीनशॉट दिखा रहे हैं जो इस value को दर्शाता है और Etherscan totalBorrow() function का result return कर रहा है।

इसी तरह, totalSupply() वह USDC की राशि नहीं है जो lenders ने Compound में जमा की है — यह कुल deposits की present value है।
नीचे दिए गए totalSupply and totalBorrow code के स्क्रीनशॉट से present value के साथ इसका संबंध स्पष्ट हो जाना चाहिए।

नीचे हमने totalSupply की दो queries का स्क्रीनशॉट दिया है। ध्यान दें कि दाईं ओर दूसरे स्क्रीनशॉट में totalSupply बढ़ गई है।

totalSupply() function ERC-20 के totalSupply() की तरह ही व्यवहार करता है।
Borrowers debt को ट्रांसफर नहीं कर सकते हैं, इसलिए totalBorrow का उपयोग किसी भी token-like interface के लिए नहीं किया जाता है।
balanceOf (Comet.sol)
BalanceOf को principal और present value के बारे में हमारी चर्चा में पहले ही कवर कर लिया गया था, इसलिए हम इसे यहाँ नहीं दोहराएंगे।
transfer और transferFrom (Comet.sol)
transfer और transferFrom दोनों ही lender की present value को ट्रांसफर करेंगे। amount parameter को present value में मापा जाता है।

ये दोनों functions background में transferInternal को कॉल करते हैं। Compound V3 में पूरा बैलेंस ट्रांसफर करने का सही तरीका uint256 max value को ट्रांसफर करना है। पूरे बैलेंस को specify करना थोड़ा मुश्किल हो सकता है क्योंकि यह हर सेकंड बढ़ता रहता है।

ध्यान दें कि borrowers के लिए collateral को अन्य addresses पर ट्रांसफर करने का कोई मैकेनिज्म नहीं है, क्योंकि transferCollateral केवल internal है। इस function का उपयोग liquidations के लिए किया जाता है।
बाकी ERC-20 functions CometExt.sol में हैं
24 KB deployment limit के कारण, Comet fallback extension pattern का उपयोग करके अपनी कुछ functionality को CometExt.sol में अलग (split) कर देता है। CometExt में अधिकांश functions ERC-20 functionality से संबंधित हैं।
approve (CometExt.sol)
cUSDCv3 के लिए approve() functionality इस मायने में non-standard है कि यह केवल type(uint256).max या zero को स्वीकार करता है। चूँकि rebasing के कारण किसी अकाउंट का बैलेंस लगातार बदलता रहता है, इसलिए किसी को सटीक रूप से पूरे बैलेंस के लिए allowance देना संभव नहीं है, क्योंकि ब्याज जमा होने के साथ बैलेंस बढ़ता रहता है।

approve() background में allowInternal को कॉल करता है जिसकी अलग से जांच करना महत्वपूर्ण है।
allow() और allowInternal()
function allow() ERC-20 का हिस्सा नहीं है, लेकिन यह approve() की तरह ही व्यवहार करता है क्योंकि यह किसी address को maximum allowance देता है। approve() और allow() दोनों किसी address को maximum allowance देने के लिए background में allowInternal() का उपयोग करते हैं।
चूँकि approve मूल रूप से binary है, इसलिए allow बिल्कुल approve की तरह व्यवहार करता है, सिवाय इसके कि यह uint256 के बजाय full value के लिए approval देने के लिए एक boolean argument लेता है।

“allowances” storage variable को CometStorage.sol में isAllowed के रूप में रखा गया है।

Compound V3 में allowance या तो सब कुछ होता है या कुछ भी नहीं। इसलिए approve केवल maximum uint256 value को स्वीकार करता है। traditional ERC-20 tokens की तरह allowance को एक नंबर के रूप में स्टोर करने के लिए कोई storage variable नहीं है।
allowance (CometExt.sol)
Allowance binary है, आपके पास केवल max uint256 value या zero के लिए approval होता है। कोई अन्य value revert हो जाएगी।
hasPermission बस एक Boolean value return करता है जो यह दर्शाता है कि किसी address के पास unlimited approvals हैं या बिल्कुल भी नहीं।
allowBySig() एक non-standard ERC-20 permit() function है
CometStorage EIP 2612 द्वारा specified nonces(address owner) external returns (uint) के बजाय mapping(address => uint256) public userNonce को एक public variable के रूप में expose करता है।
name() और symbol() (CometExt.sol)
functions name() और symbol() optional ERC-20 functions हैं जो strings return करते हैं।
CometExt.sol gas efficiency के उद्देश्यों के लिए इन values को string variables में स्टोर नहीं करता है, बल्कि इसके बजाय immutable bytes32 variables में स्टोर करता है। Solidity सीधे bytes32 को strings में cast करने की अनुमति नहीं देती है, इसलिए immutable variables को नीचे दिए गए कोड का उपयोग करके तुरंत (on the fly) strings में convert किया जाता है।
Solidity में bytes1, bytes2, …, और bytes32 datatypes के बारे में एक कम ज्ञात बात यह है कि उन्हें byte arrays की तरह byte level पर index किया जा सकता है। उदाहरण के लिए,
contract Example {
bytes32 immutable x = 0x3300000000000000000000000000000000000000000000000000000000000000;
function main() external pure returns (bytes1) {
return x[0]; // returns 0x33
}
}
CometExt memory में एक bytes array को initialize करता है और name32 तथा symbol32 bytes32 immutable variables में स्टोर किए गए characters को कॉपी करता है, फिर उसे एक string में cast कर देता है।

CometExt में functions को कॉल करना
Etherscan को ज्ञात ABI को इन functions के बारे में पता नहीं होता है, इसलिए वे Comet functions की लिस्ट में दिखाई नहीं देंगे। हालाँकि, उन्हें कॉल किया जा सकता है क्योंकि वे Comet के fallback को हिट करेंगे और CometExt contract को delegate कर दिए जाएंगे।
यहाँ Foundry के cast का उपयोग करके name() और symbol() को कॉल करने का एक उदाहरण दिया गया है।

निष्कर्ष
CometV3 एक rebasing ERC-20 token की तरह व्यवहार करता है जो lenders के positive balances का प्रतिनिधित्व करता है। इस positive balance को एक regular ERC-20 token की तरह अन्य addresses पर ट्रांसफर किया जा सकता है। approve() function non-standard है — यह केवल infinite approve कर सकता है या बिल्कुल भी नहीं कर सकता। इसी तरह, gasless approvals के लिए permit() function भी non-standard है।
RareSkills के साथ और जानें
अधिक जानकारी के लिए हमारा blockchain bootcamp देखें।
मूल रूप से 7 जनवरी, 2024 को प्रकाशित