ERC-7730 वापरून तुमच्या प्रोटोकॉलमध्ये क्लिअर स्वाक्षरी जोडा
बहुतेक मोठ्या इथेरियम (Ethereum) शोषणांमध्ये (exploits) एकच अंतिम टप्पा होता: वापरकर्त्याने असा व्यवहार मंजूर करणे जो त्यांना अर्थपूर्णरीत्या समजू शकत नव्हता. हार्डवेअर वॉलेट्स कच्चा हेक्स कॉल डेटा (raw hex calldata) दाखवतात आणि त्याहून वाईट म्हणजे तुम्हाला ब्लाइंड स्वाक्षरी (blind signing) चालू ठेवण्यास भाग पाडतात. सॉफ्टवेअर वॉलेट्स डीकोड केलेले फील्ड्स दाखवतात, परंतु केवळ तेव्हाच जेव्हा ते कॉन्ट्रॅक्ट ओळखतात. जेव्हा ते ओळखत नाहीत, मग ते प्रोटोकॉल नवीन असल्यामुळे असो, ॲप तडजोड केलेले (compromised) असल्यामुळे असो, किंवा डिव्हाइस ऑफलाइन असल्यामुळे असो, वापरकर्ते ब्लाइंड स्वाक्षरी करतात.
ERC-7730 (नवीन टॅबमध्ये उघडते) तुमच्या कॉन्ट्रॅक्टच्या फंक्शन कॉल्सचा अर्थ काय आहे हे वर्णन करण्यासाठी एक प्रमाणित JSON फॉरमॅट परिभाषित करते.
ERC-7730 ला सपोर्ट करणारे वॉलेट तुमचा डिस्क्रिप्टर वाचते आणि खालीलप्रमाणे दाखवते:
अदलाबदल (Swap)
पाठवा: 1,000 USDC
किमान प्राप्त करा: 0.42 WETH
प्रोटोकॉल: युनिस्वॅप V3 (Uniswap V3)
किंवा मानवांना आणि एजंट्सना सारखेच वाचता येईल असे एकच तयार केलेले वाक्य:
किमान 0.42 WETH साठी 1,000 USDC ची अदलाबदल करा
फंक्शन सिलेक्टर आणि कच्च्या पूर्णांक मूल्यांच्या (raw integer values) सूचीऐवजी.
याला क्लिअर स्वाक्षरी (clear signing) (नवीन टॅबमध्ये उघडते) म्हणतात — "तुम्ही जे पाहता त्यावरच तुम्ही स्वाक्षरी करता." हे ट्युटोरियल तुम्हाला तुमच्या स्वतःच्या कॉन्ट्रॅक्टसाठी डिस्क्रिप्टर लिहिणे, अधिकृत CLI टूलसह त्याचे प्रमाणीकरण करणे आणि ते खुल्या रजिस्ट्रीमध्ये सबमिट करणे याबद्दल मार्गदर्शन करते.
पूर्वअटी
- Solidity आणि स्मार्ट कॉन्ट्रॅक्ट ABIs ची माहिती
- सत्यापित ABI सह प्रस्थापित केलेले (deployed) स्मार्ट कॉन्ट्रॅक्ट (डिस्क्रिप्टर रजिस्ट्रीमध्ये स्वीकारण्यापूर्वी Sourcify (नवीन टॅबमध्ये उघडते) सत्यापन आवश्यक आहे)
- प्रमाणीकरण CLI साठी Python 3.12+
- JSON चे मूलभूत ज्ञान
ERC-7730 डिस्क्रिप्टर म्हणजे काय?
डिस्क्रिप्टर ही तीन विभागांसह असलेली एकच JSON फाईल असते:
| विभाग (Section) | उद्देश (Purpose) |
|---|---|
context | चेन आयडी (chain ID) आणि पत्त्याद्वारे डिस्क्रिप्टरला विशिष्ट कॉन्ट्रॅक्ट प्रस्थापनांशी (deployments) जोडते |
metadata | प्रकल्पाला नाव देते आणि पुन्हा वापरता येण्याजोगे स्थिरांक (constants) परिभाषित करते |
display | प्रत्येक फंक्शन स्वाक्षरीला मानवी-वाचनीय लेबल्स आणि फील्ड फॉरमॅट्सशी मॅप करते |
डिस्क्रिप्टर कॉन्ट्रॅक्टपासून वेगळा असल्यामुळे, तुम्ही पुन्हा प्रस्थापना (redeployment) न करता कोणत्याही विद्यमान प्रोटोकॉलमध्ये क्लिअर स्वाक्षरी सपोर्ट जोडू शकता. वॉलेट्स रजिस्ट्रीमधून डिस्क्रिप्टर्स मिळवतात आणि स्वाक्षरी करण्याच्या वेळी त्यांचा वापर करतात.
पायरी 1: फाईलचा सांगाडा (skeleton) तयार करा
calldata-<contractname>-<descriptorversion>.json नावाची फाईल तयार करा. calldata- उपसर्ग (prefix) रजिस्ट्रीला सांगतो की हा डिस्क्रिप्टर कॉन्ट्रॅक्ट फंक्शन कॉल्स कव्हर करतो, याउलट eip712- टाईप-डेटा मेसेजेससाठी असतो. descriptorversion रजिस्ट्रीला डिस्क्रिप्टर फाईलची आवृत्ती सांगते, कोणतीही आवृत्ती न दिल्यास ती डीफॉल्टनुसार 0 असते.
{
"$schema": "https://eips.ethereum.org/assets/eip-7730/erc7730-v2.schema.json",
"context": {},
"metadata": {},
"display": {
"formats": {}
}
}
पायरी 2: संदर्भ (context) विभाग लिहा
context विभाग डिस्क्रिप्टरला एक किंवा अधिक कॉन्ट्रॅक्ट प्रस्थापनांशी जोडतो. वॉलेट्स येणाऱ्या व्यवहाराला योग्य डिस्क्रिप्टरशी जुळवण्यासाठी याचा वापर करतात.
"context": {
"$id": "uniswap-v3-router-mainnet",
"contract": {
"deployments": [
{ "chainId": 1, "address": "0xYourContractAddressOnMainnet" },
{ "chainId": 137, "address": "0xYourContractAddressOnPolygon" }
]
}
}
संदर्भ फील्ड्स (Context fields)
context.$id— या डिस्क्रिप्टर दस्तऐवजासाठी किंवा प्रस्थापना कॉन्फिगरेशनसाठी एक युनिक आयडेंटिफायर.contract.deployments— प्रस्थापनांचा संच ज्यांना हा डिस्क्रिप्टर लागू होतो.deployments[].chainId— प्रस्थापनेसाठी EVM चेन आयडी. तुमचे कॉन्ट्रॅक्ट प्रस्थापित केलेल्या प्रत्येक चेनचा समावेश करा.deployments[].address— वॉलेट्सनी या डिस्क्रिप्टरशी जोडला पाहिजे असा कॉन्ट्रॅक्ट पत्ता. अंमलबजावणी लॉजिक (execution logic) असलेल्या अंमलबजावणी पत्त्याचा (implementation address) वापर करा.
पायरी 3: मेटाडेटा विभाग लिहा
मेटाडेटा विभाग या फाईलद्वारे वर्णन केलेल्या प्रकल्पाबद्दल आणि कॉन्ट्रॅक्टबद्दल मानवी-वाचनीय माहिती प्रदान करतो. वॉलेट्स स्वाक्षरी करताना प्रोटोकॉलची नावे, लिंक्स आणि इतर संदर्भात्मक तपशील प्रदर्शित करण्यासाठी या माहितीचा वापर करू शकतात.
"metadata": {
"owner": "Example Swap Protocol",
"info": { "url": "https://example.xyz" },
"contractName": "SwapRouter"
}
मेटाडेटा फील्ड्स
owner— या डिस्क्रिप्टरसाठी जबाबदार असलेला प्रकल्प, प्रोटोकॉल, संस्था किंवा देखभालकर्ता (maintainer).info.url— अतिरिक्त संदर्भासाठी वॉलेट्स वापरकर्त्यांना दाखवू शकतील अशी अधिकृत प्रकल्प किंवा दस्तऐवजीकरण URL.contractName— या फाईलद्वारे वर्णन केलेले कॉन्ट्रॅक्ट किंवा अंमलबजावणीचे नाव, जे सामान्यतः सत्यापित सोर्स कोड किंवा ABI शी जुळते.
जर तुमची ERC-7730 फाईल ERC-20 कॉन्ट्रॅक्टचे वर्णन करत असेल, तर तुम्ही टोकन ऑब्जेक्ट देखील जोडला पाहिजे.
पायरी 4: डिस्प्ले फॉरमॅट्स विभाग लिहा
display.formats ऑब्जेक्ट फंक्शन स्वाक्षऱ्या मानवी-वाचनीय स्वाक्षरी सूचनांशी मॅप करतो. अशा प्रकारे वापरकर्त्यांनी व्यवहार मंजूर करण्यापूर्वी वॉलेट्स तुमचे फंक्शन त्यांना दाखवतात!
प्रत्येक की (key) एक मानवी-वाचनीय ABI फ्रॅगमेंट आहे — फंक्शन स्वाक्षरी ज्यामध्ये पॅरामीटरची नावे आणि पॅरामीटरचे प्रकार दोन्ही तुमच्या ABI मध्ये जसे दिसतात अगदी तसेच समाविष्ट असतात.
उदाहरण: टोकन अदलाबदलीचे वर्णन करणे
"display": {
"formats": {
"swapExactTokensForTokens(uint256 amountIn,uint256 amountOutMin,address[] path,address to,uint256 deadline)": {
"intent": "Swap",
"interpolatedIntent": "Swap {amountIn} for at least {amountOutMin}",
"fields": [
{
"path": "#.amountIn",
"label": "Send",
"format": "tokenAmount",
"params": {
"tokenPath": "#.path[0]"
}
},
{
"path": "#.amountOutMin",
"label": "Receive minimum",
"format": "tokenAmount",
"params": {
"tokenPath": "#.path[1]"
}
},
{
"path": "#.to",
"label": "Recipient",
"format": "addressName",
"params": {
"types": ["eoa", "contract"],
"sources": ["local", "ens"]
}
},
{
"path": "#.deadline",
"label": "Expires",
"format": "date",
"params": {
"encoding": "timestamp"
}
}
]
}
}
}
डिस्प्ले फील्ड्स
intent— (आवश्यक) क्रियेचे एक छोटे, वापरकर्ता-अनुकूल वर्णन, जसे की "अदलाबदल (Swap)".interpolatedIntent— (शिफारस केलेले) एक अधिक समृद्ध वाक्य टेम्पलेट जे फॉरमॅट केलेली फील्ड मूल्ये एम्बेड करते, जसे की"Swap {amountIn} for at least {amountOutMin}". वॉलेट्स कोणत्याही डिस्प्ले मर्यादांनुसार दाखवण्यासाठी निवडू शकतील असा अधिक वापरकर्ता-अनुकूल डिस्क्रिप्टर प्रदान करण्यासाठीintentसोबत याचा समावेश करा.fields— (आवश्यक) वॉलेट्सनी वापरकर्त्यांना दाखवायच्या व्यवहार फील्ड्सची क्रमित सूची.-
path— (आवश्यक) व्यवहार डेटाचा संदर्भ.#.fieldNameABI मधील नावानुसार डीकोड केलेल्या कॉल डेटा पॅरामीटरकडे निर्देश करते.@.valueव्यवहारासोबत पाठवलेल्या ETH मूल्याचा संदर्भ देते. -
label— (आवश्यक) मूल्याच्या बाजूला दाखवलेले मानवी-वाचनीय लेबल. -
format— (शिफारस केलेले) मूल्य कसे रेंडर केले जावे हे नियंत्रित करते. सामान्य फॉरमॅट्समध्ये हे समाविष्ट आहे:tokenAmountaddressNamedate
जेव्हा कोणत्याही अतिरिक्त फॉरमॅटिंगची आवश्यकता नसते तेव्हा
rawवापरा. काही फॉरमॅट्स अतिरिक्तparamsकॉन्फिगरेशन स्वीकारतात. उदाहरणार्थ:- कोणता टोकन पत्ता डेसिमल्स आणि टिकर मेटाडेटा प्रदान करतो हे ओळखण्यासाठी
tokenAmountहेtokenPathवापरू शकते. - टाइमस्टॅम्प कसा एन्कोड केला आहे याचे वर्णन करण्यासाठी
dateहेencodingवापरू शकते.
निवडलेल्या फॉरमॅटला अतिरिक्त माहितीची आवश्यकता नसल्यास,
paramsवगळा.
-
संपूर्ण डिस्क्रिप्टर
{
"$schema": "https://eips.ethereum.org/assets/eip-7730/erc7730-v2.schema.json",
"context": {
"$id": "uniswap-v3-router-mainnet",
"contract": {
"deployments": [
{
"chainId": 1,
"address": "0xYourContractAddressOnMainnet"
},
{
"chainId": 137,
"address": "0xYourContractAddressOnPolygon"
}
]
}
},
"metadata": {
"owner": "Example Swap Protocol",
"info": {
"url": "https://example.xyz"
},
"contractName": "SwapRouter"
},
"display": {
"formats": {
"swapExactTokensForTokens(uint256 amountIn,uint256 amountOutMin,address[] path,address to,uint256 deadline)": {
"intent": "Swap",
"interpolatedIntent": "Swap {amountIn} for at least {amountOutMin}",
"fields": [
{
"path": "#.amountIn",
"label": "Send",
"format": "tokenAmount",
"params": {
"tokenPath": "#.path[0]"
}
},
{
"path": "#.amountOutMin",
"label": "Receive minimum",
"format": "tokenAmount",
"params": {
"tokenPath": "#.path[1]"
}
},
{
"path": "#.to",
"label": "Recipient",
"format": "addressName",
"params": {
"types": ["eoa", "contract"],
"sources": ["local", "ens"]
}
},
{
"path": "#.deadline",
"label": "Expires",
"format": "date",
"params": {
"encoding": "timestamp"
}
}
]
}
}
}
}
पायरी 5: रजिस्ट्रीमध्ये सबमिट करा
ERC-7730 रजिस्ट्री (नवीन टॅबमध्ये उघडते) ही एक तटस्थ व्यवस्थापक (neutral steward) म्हणून इथेरियम फाउंडेशन द्वारे होस्ट केलेली एक खुली रिपॉझिटरी आहे. कोणालाही ती क्लोन आणि सेल्फ-होस्ट करण्याचे स्वातंत्र्य आहे — वॉलेट्स स्वतंत्रपणे ठरवतात की ते कोणत्या रजिस्ट्री इन्स्टन्सेसवर विश्वास ठेवतात.
- GitHub वर रिपॉझिटरी फोर्क (Fork) करा
registry/<your-project-name>/येथे एक फोल्डर तयार करा- तुमची फाईल त्यामध्ये ठेवा:
registry/myproject/calldata-mycontract-0_0.json $schemaफील्डला रेपोमध्ये वापरलेल्या रिलेटिव्ह पाथवर अपडेट करा:"../../specs/erc7730-v2.schema.json"- पुल रिक्वेस्ट (pull request) उघडा
जेव्हा तुम्ही PR उघडता, तेव्हा CI आपोआप स्कीमा प्रमाणीकरण चालवते, फंक्शन स्वाक्षऱ्या वैध सिलेक्टर्स तयार करतात का ते तपासते, कॉन्ट्रॅक्ट पत्ता Sourcify वर सत्यापित असल्याची पुष्टी करते आणि ABI विसंगती फ्लॅग करते. तपासणीचे परिणाम PR वर इनलाइन दिसतात. रजिस्ट्री देखभालकर्ते सदोष किंवा संभाव्य दुर्भावनापूर्ण डिस्क्रिप्टर्ससाठी सबमिशन्सची छाननी करतात. रजिस्ट्रीमध्ये समाविष्ट करणे म्हणजे ऑडिट किंवा समर्थन (endorsement) असा होत नाही.
विलीनीकरणानंतर (merging) काय होते?
रजिस्ट्रीमधील सर्व डिस्क्रिप्टर्स ऑडिटर्ससाठी खुले असतात. तुमची PR विलीन झाल्यानंतर, कोणताही ऑडिटर तुमच्या डिस्क्रिप्टरचे पुनरावलोकन करू शकतो आणि त्याच्या अचूकतेची पुष्टी करणारे क्रिप्टोग्राफिक साक्षांकन (ERC-8176 (नवीन टॅबमध्ये उघडते) अंतर्गत) प्रकाशित करू शकतो.
हे साक्षांकन सिग्नल्स वॉलेट्सना त्यांची स्वतःची विश्वास धोरणे (trust policies) लागू करू देतात — एकाधिक स्वतंत्र साक्षांकन असलेल्या डिस्क्रिप्टरला त्याशिवाय असलेल्या डिस्क्रिप्टरपेक्षा जास्त महत्त्व असते. तुम्ही clearsigning.org (नवीन टॅबमध्ये उघडते) द्वारे ऑडिटर समुदायापर्यंत पोहोचू शकता.
वॉलेट्स ते कोणत्या रजिस्ट्रीला सपोर्ट करतील हे निवडतात. एकदा तुमचा डिस्क्रिप्टर रजिस्ट्रीमध्ये आला की, ERC-7730 ला सपोर्ट करणारी वॉलेट्स तो त्यांच्या रजिस्ट्रीमध्ये असल्यास मिळवणे सुरू करतील आणि जेव्हा वापरकर्ते तुमच्या कॉन्ट्रॅक्टशी संवाद साधतील तेव्हा मानवी-वाचनीय डेटा प्रदर्शित करतील.