QA डैशबोर्ड स्मार्ट कॉन्ट्रैक्ट स्थिति की निगरानी कर रहा है पिछली पोस्ट में एक संपूर्ण कार्यान्वयन के बारे में बताया गया था: एक न्यूनतम टोकन कॉन्ट्रैक्ट, ऑफ-चेन स्थिति रिकोQA डैशबोर्ड स्मार्ट कॉन्ट्रैक्ट स्थिति की निगरानी कर रहा है पिछली पोस्ट में एक संपूर्ण कार्यान्वयन के बारे में बताया गया था: एक न्यूनतम टोकन कॉन्ट्रैक्ट, ऑफ-चेन स्थिति रिको

एथेरियम अकाउंट स्टेट: मिनिमल टोकन के लिए QA पाइपलाइन

2026/04/09 13:48
9 मिनट पढ़ें
इस कॉन्टेंट के संबंध में प्रतिक्रिया या चिंताओं के लिए, कृपया crypto.news@mexc.com पर हमसे संपर्क करें
स्मार्ट कॉन्ट्रैक्ट स्थिति की निगरानी करने वाला QA डैशबोर्ड

पिछली पोस्ट में एंड-टू-एंड कार्यान्वयन के बारे में बताया गया था: एक न्यूनतम टोकन कॉन्ट्रैक्ट, ऑफ-चेन स्थिति पुनर्निर्माण, और एक React फ्रंटएंड — `mint()` से लेकर MetaMask तक। यह पोस्ट वहीं से शुरू होती है जहां वह छूटी थी: आप इस तरह की चीज़ का QA कैसे करते हैं?

मैं एक ब्लॉकचेन इंजीनियर नहीं हूं (अभी तक), लेकिन QA पैटर्न डोमेन में अच्छी तरह से काम करते हैं, और जो पहले से कहीं और काम करता है उसे उधार लेना मेरे लिए सबसे तेज़ सीखने का तरीका है।

कॉन्ट्रैक्ट केवल तीन काम करता है: `mint`, `transfer`, और `burn`, लेकिन यह पूर्ण QA टूलचेन का अभ्यास करने के लिए पर्याप्त है: स्टैटिक एनालिसिस, म्यूटेशन टेस्टिंग, गैस प्रोफाइलिंग, फॉर्मल वेरिफिकेशन।

कोड `egpivo/ethereum-account-state` में है।

ब्लॉकचेन QA पिरामिड: आधार पर स्टैटिक एनालिसिस से लेकर शीर्ष पर फॉर्मल वेरिफिकेशन तक

हमने किस चीज़ से शुरुआत की

कुछ नया जोड़ने से पहले, प्रोजेक्ट में पहले से ही था:

  • 21 Foundry यूनिट टेस्ट जो प्रत्येक स्थिति संक्रमण को कवर करते हैं (सफलता, अवैध इनपुट पर रिवर्ट, इवेंट एमिशन)
  • 3 इनवेरिएंट टेस्ट एक `TokenHandler` के माध्यम से जो 10 एक्टर्स पर `mint`/`transfer`/`burn` के रैंडम सीक्वेंस चलाता है (प्रत्येक में 128k कॉल)
  • फज़ टेस्ट रैंडम राशियों के लिए `sum(balances) == totalSupply` की जांच करते हैं
  • TypeScript डोमेन टेस्ट (Vitest) जो ऑन-चेन स्टेट मशीन को मिरर करते हैं
  • CI: कंपाइल, टेस्ट, लिंट (Prettier + solhint)

सभी टेस्ट पास हुए। कवरेज ठीक लग रही थी। तो फिर और अधिक की परेशानी क्यों?

क्योंकि "सभी टेस्ट पास" का मतलब यह नहीं है कि "सभी बग पकड़े गए।" 100% लाइन कवरेज अभी भी एक वास्तविक बग को मिस कर सकती है अगर कोई एसर्शन सही चीज़ की जांच नहीं करता है।

चरण 1: स्मार्ट कॉन्ट्रैक्ट स्टैटिक एनालिसिस और कवरेज

Slither

Slither(Trail of Bits) उन समस्याओं को पकड़ता है जो टेस्ट के लिए अदृश्य हैं: रीएंट्रेंसी, अनचेक्ड रिटर्न वैल्यू, इंटरफ़ेस मिसमैच।

./scripts/run-qa.sh slither

परिणाम: 1 मध्यम खोज: `erc20-interface`: `transfer()` `bool` रिटर्न नहीं करता है।

यह अपेक्षित है। कॉन्ट्रैक्ट जानबूझकर पूर्ण ERC20 नहीं है: यह एक शैक्षिक स्टेट मशीन है। लेकिन यह खोज शैक्षणिक नहीं है:

अगर कोई बाद में इस टोकन को ERC20 की अपेक्षा करने वाले प्रोटोकॉल में इम्पोर्ट करता है, तो इंटरफ़ेस मिसमैच चुपचाप विफल हो जाएगा। Slither इसे अभी फ्लैग करता है ताकि निर्णय सचेत हो।

कवरेज

./scripts/run-qa.sh coverageकवरेज परिणाम।

एक अनकवर्ड फंक्शन: `BalanceLib.gt()`। हम इस पर वापस आएंगे।

forge कवरेज आउटपुट: 24 टेस्ट पास, Token.sol कवरेज टेबल

गैस स्नैपशॉट

./scripts/run-qa.sh gas

तीन ऑपरेशंस के लिए बेसलाइन गैस लागत:

ऑपरेशंस के संदर्भ में गैस

बाद के रन पर, `forge snapshot — diff` बेसलाइन के साथ तुलना करता है। `transfer()` में 20% गैस रिग्रेशन हर यूज़र के लिए एक वास्तविक लागत है — इसे मर्ज से पहले पकड़ना सस्ता है।

चरण 2: म्यूटेशन टेस्टिंग और फॉर्मल वेरिफिकेशन

म्यूटेशन टेस्टिंग (Gambit)

यहाँ चीजें दिलचस्प हो गईं। Gambit(Certora) म्यूटेंट: `Token.sol` की कॉपियाँ छोटे जानबूझकर बग के साथ जनरेट करता है (`+=` से `-=`, `>=` से `>`, शर्तें नेगेट की गईं)। पाइपलाइन प्रत्येक म्यूटेंट के खिलाफ पूर्ण टेस्ट सूट चलाती है। अगर कोई म्यूटेंट जीवित रहता है (सभी टेस्ट अभी भी पास होते हैं), तो वह एक ठोस टेस्ट गैप है।

./scripts/run-qa.sh mutation

परिणाम: 97.0% म्यूटेशन स्कोर — 33 म्यूटेंट में से 32 मारे गए, 1 जीवित रहा।

Gambit का आउटपुट लॉग प्रत्येक म्यूटेंट और उसने क्या बदला दिखाता है। कुछ उदाहरण:

जनरेटेड म्यूटेंट #7: BinaryOpMutation — Token.sol:168
totalSupply = totalSupply.add(amountBalance) → totalSupply = totalSupply.sub(amountBalance)
test_Mint_Success द्वारा मारा गया
जनरेटेड म्यूटेंट #19: RelationalOpMutation — Token.sol:196
if (!fromBalance.gte(amountBalance)) → if (fromBalance.gte(amountBalance))
test_Transfer_Success द्वारा मारा गया
जनरेटेड म्यूटेंट #28: SwapArgumentsMutation — Token.sol:81
return Balance.unwrap(a) > Balance.unwrap(b) → return Balance.unwrap(b) > Balance.unwrap(a)
जीवित रहा ← किसी टेस्ट ने इसे नहीं पकड़ाGambit म्यूटेशन टेस्टिंग: 32 मारे गए, 1 जीवित रहा, म्यूटेशन स्कोर 97.0%

जीवित रहने वाले म्यूटेंट ने `BalanceLib.gt()` में `a > b` को `b > a` से स्वैप कर दिया। किसी टेस्ट ने इसे नहीं पकड़ा क्योंकि `gt()` डेड कोड है। यह `Token.sol` में कहीं भी कॉल नहीं किया जाता है।

कवरेज ने 91.67% फंक्शंस को फ्लैग किया लेकिन गैप को समझा नहीं सका। म्यूटेशन टेस्टिंग ने किया: `gt()` डेड कोड है, कुछ भी इसे कॉल नहीं करता है, और कोई भी नोटिस नहीं करेगा अगर यह गलत था।

स्मार्ट कॉन्ट्रैक्ट्स में डेड या अनप्रोटेक्टेड कोड का वास्तविक उदाहरण है।

फंक्शन कॉल करने योग्य नहीं था, लेकिन किसी ने भी उस धारणा का परीक्षण नहीं किया। हमारा `gt()` तुलनात्मक रूप से हानिरहित है, लेकिन पैटर्न समान है: कोड जो मौजूद है लेकिन कभी एक्सरसाइज नहीं किया जाता है वह कोड है जिसे कोई नहीं देख रहा है।

फॉर्मल वेरिफिकेशन (Halmos)

Halmos(a16z) सभी संभावित इनपुट के बारे में प्रतीकात्मक रूप से तर्क करता है। जहाँ फज़ टेस्ट रैंडम वैल्यू सैंपल करते हैं और एज केस हिट करने की उम्मीद करते हैं, Halmos प्रॉपर्टीज को संपूर्ण रूप से साबित करता है।

./scripts/run-qa.sh halmos

परिणाम: 9/9 सिंबोलिक टेस्ट पास — सभी इनपुट के लिए सभी प्रॉपर्टीज साबित हुईं।

सत्यापित प्रॉपर्टीज:

सत्यापित प्रॉपर्टीज

एक व्यावहारिक नोट: Halmos 0.3.3 `vm.expectRevert()` का समर्थन नहीं करता है, इसलिए मैं सामान्य Foundry तरीके से रिवर्ट टेस्ट नहीं लिख सका। वर्कअराउंड एक try/catch पैटर्न है — अगर कॉल सफल होती है जब उसे रिवर्ट करना चाहिए, `assert(false)` प्रूफ को विफल करता है:

function check_mint_reverts_on_zero_address(uint256 amount) public {
vm.assume(amount > 0);
try token.mint(address(0), amount) {
assert(false); // यहाँ नहीं पहुँचना चाहिए
} catch {
// अपेक्षित रिवर्ट - Halmos साबित करता है कि यह पथ हमेशा लिया जाता है
}
}

सबसे सुंदर नहीं, लेकिन यह काम करता है — Halmos अभी भी सभी इनपुट के लिए प्रॉपर्टी साबित करता है। यह उस तरह की चीज़ है जो आप केवल टूल को वास्तव में चलाकर पता लगा सकते हैं।

फॉर्मल वेरिफिकेशन क्यों मायने रखता है इसके संदर्भ में:

कमजोरी कोड में थी, किसी द्वारा भी समीक्षा योग्य थी, लेकिन कोई टूल या टेस्ट ने इसे डिप्लॉयमेंट से पहले नहीं पकड़ा। Halmos जैसे सिंबोलिक प्रूवर ठीक उस गैप को बंद करने के लिए मौजूद हैं — वे सैंपल नहीं करते; वे इनपुट स्पेस को एक्झॉस्ट करते हैं।

Halmos आउटपुट: 9 टेस्ट पास, 0 विफल, सिंबोलिक टेस्ट परिणाम

टेस्ट फाइल `contracts/test/Token.halmos.t.sol` है।

चरण 3: क्रॉस-लेयर प्रॉपर्टी टेस्टिंग

पहली पोस्ट की आर्किटेक्चर में एक TypeScript डोमेन लेयर है जो ऑन-चेन स्टेट मशीन को मिरर करती है। यह चरण परीक्षण करता है कि क्या दोनों वास्तव में सहमत हैं।

fast-check के साथ प्रॉपर्टी-आधारित टेस्टिंग

मैंने TypeScript डोमेन लेयर के लिए fast-check प्रॉपर्टी टेस्ट जोड़े, जो Foundry का फज़र Solidity के लिए करता है उसे मिरर करते हुए:

npm test - tests/unit/property.test.ts

परिणाम: एक वास्तविक बग को ठीक करने के बाद 9/9 प्रॉपर्टी टेस्ट पास

परीक्षित प्रॉपर्टीज:

  • `Balance`: कम्यूटेटिविटी, एसोसिएटिविटी, आइडेंटिटी, इनवर्स, तुलना स्थिरता
  • `Token`: रैंडम ऑपरेशन सीक्वेंस के तहत इनवेरिएंट `sum(balances) == totalSupply` (200 रन, प्रत्येक में 50 ऑप्स)
  • `Token`: रैंडम सीक्वेंस के बाद `totalSupply` नॉन-नेगेटिव
  • `mint` वैलिड इनपुट के लिए हमेशा सफल होता है
  • `transfer` `totalSupply` को संरक्षित करता है

fast-check ने जो बग पाया

fast-check ने `Token.ts` `transfer()` में एक वास्तविक क्रॉस-लेयर स्थिरता बग पाया। सिकुड़ा हुआ काउंटरएग्जाम्पल तुरंत स्पष्ट था:

3 टेस्ट के बाद प्रॉपर्टी विफल
2 बार सिकुड़ा
काउंटरएग्जाम्पल: transfer(from=0xaaa…, to=0xaaa…, amount=1n)
→ from == to (सेल्फ-ट्रांसफर)
→ verifyInvariant() ने false रिटर्न किया

सेल्फ-ट्रांसफर (`from == to`) ने `sum(balances) == totalSupply` इनवेरिएंट को तोड़ दिया। `toBalance` को `fromBalance` अपडेट होने से पहले पढ़ा गया था, इसलिए जब `from == to`, स्टेल वैल्यू ने डिडक्शन को ओवरराइट किया:

// पहले (बगी)
const fromBalance = this.getBalance(from);
const toBalance = this.getBalance(to); // ← स्टेल जब from == to
this.accounts.set(from.getValue(), fromBalance.subtract(amount));
this.accounts.set(to.getValue(), toBalance.add(amount)); // ← सबट्रैक्शन को ओवरराइट करता है

ठीक करें: `fromBalance` लिखने के बाद `toBalance` पढ़ें, Solidity के स्टोरेज सेमेंटिक्स से मेल खाते हुए:

// बाद में (ठीक किया गया)
const fromBalance = this.getBalance(from);
this.accounts.set(from.getValue(), fromBalance.subtract(amount));
const toBalance = this.getBalance(to); // ← अब अपडेटेड वैल्यू पढ़ता है
this.accounts.set(to.getValue(), toBalance.add(amount));

Solidity कॉन्ट्रैक्ट प्रभावित नहीं था: यह प्रत्येक राइट के बाद स्टोरेज को फिर से पढ़ता है। लेकिन TypeScript मिरर में एक सूक्ष्म ऑर्डरिंग निर्भरता थी जिसे कोई मौजूदा यूनिट टेस्ट कवर नहीं करता था।

बड़े पैमाने पर क्रॉस-लेयर मिसमैच विनाशकारी रहे हैं।

हमारा सेल्फ-ट्रांसफर बग किसी का भी पैसा नहीं खोता, लेकिन विफलता मोड संरचनात्मक रूप से समान है: दो लेयर जो सहमत होने वाली थीं, नहीं हैं।

रास्ते में आई बाधाएं

मौजूदा प्रोजेक्ट पर QA टूल चलाना कभी भी केवल "इंस्टॉल और रन" नहीं है। काम करने से पहले कुछ चीज़ें टूटीं:

  • 0% कवरेज क्योंकि `foundry.toml` में कोई टेस्ट पथ नहीं था: पहला `forge coverage` रन बोर्ड भर में 0% रिटर्न किया। पता चला कि `foundry.toml` ने `test = "contracts/test"` या `script = "contracts/script"` निर्दिष्ट नहीं किया था, इसलिए Forge किसी टेस्ट की खोज नहीं कर रहा था। कवरेज कमांड चुपचाप सफल रहा — बस इसके पास कवर करने के लिए कुछ नहीं था। यह सबसे भ्रामक विफलता थी: कोई उपयोगी आउटपुट के बिना एक ग्रीन रन।
  • forge-std v1.14.0 में `InvariantTest` इम्पोर्ट गया: `Invariant.t.sol` ने `forge-std` से `InvariantTest` इम्पोर्ट किया, जिसे एक हाल की रिलीज़ में हटा दिया गया था। कंपाइलेशन एक अस्पष्ट "symbol not found" एरर के साथ विफल रहा। ठीक करना इम्पोर्ट को ड्रॉप करना था — अब Foundry के इनवेरिएंट टेस्टिंग के लिए अकेला `Test` पर्याप्त है।
  • `uint256(token.totalSupply())` बनाम `Balance.unwrap()`: टेस्ट यूज़र-डिफाइंड `Balance` टाइप से अंतर्निहित `uint256` को एक्सट्रैक्ट करने के लिए एक स्पष्ट कास्ट का उपयोग कर रहे थे। यह कंपाइल हुआ, लेकिन यह गलत मुहावरा है — `Balance.unwrap(token.totalSupply())` वह है जिसके लिए UDVT सिस्टम डिज़ाइन किया गया है। `Token.t.sol`, `Invariant.t.sol`, और `DeploySepolia.s.sol` भर में लागू किया गया।

पाइपलाइन डिज़ाइन

सब कुछ दो स्क्रिप्ट के माध्यम से चलता है:

  • scripts/setup-qa-tools.sh`: Slither, Halmos, Gambit इंस्टॉल करता है (idempotent)
  • `scripts/run-qa.sh`: चेक चलाता है, टाइमस्टैम्प्ड परिणाम `qa-results/` में सेव करता है

./scripts/run-qa.sh slither gas # बस स्टैटिक एनालिसिस + गैस
./scripts/run-qa.sh mutation # बस म्यूटेशन टेस्टिंग
./scripts/run-qa.sh all # सब कुछ

हर चेक तेज़ नहीं है। Slither और कवरेज हर कमिट पर चलते हैं। म्यूटेशन टेस्टिंग और Halmos धीमे हैं — साप्ताहिक या प्री-रिलीज़ रन के लिए बेहतर अनुकूल।

सारांश

ब्लॉकचेन QA टूलचेन: प्रत्येक लेयर क्या पकड़ती है — स्टैटिक एनालिसिस से लेकर क्रॉस-लेयर प्रॉपर्टी टेस्टिंग तक

पाँच QA लेयर, प्रत्येक समस्या के एक अलग वर्ग को पकड़ती है।

लेयर स्पष्टीकरण

Gambit और fast-check ने इस राउंड में सबसे अधिक कार्रवाई योग्य परिणाम दिए।

CI पाइपलाइन

QA चेक अब GitHub Actions में एक छह-चरण पाइपलाइन के रूप में वायर्ड हैं:

CI पाइपलाइन: Build & Lint Test, Coverage, Gas, Slither, और Audit चरणों में फैलता है

GitHub Actions पाइपलाइन: Build & Lint सभी डाउनस्ट्रीम चरणों को गेट करता है।

चरण स्पष्टीकरण

संदर्भ

  • Ethereum Account State स्रोत: [github.com/egpivo/ethereum-account-state](https://github.com/egpivo/ethereum-account-state)
  • पिछली पोस्ट: Ethereum Account State
  • Slither: github.com/crytic/slither
  • Gambit: github.com/Certora/gambit
  • Halmos: github.com/a16z/halmos
  • fast-check: github.com/dubzzz/fast-check
  • Foundry: getfoundry.sh

नोट्स

  • यह पोस्ट मेरी मूल ब्लॉग पोस्ट से अनुकूलित है।

Ethereum Account State: QA Pipeline for a Minimal Token मूल रूप से Medium पर Coinmonks में प्रकाशित हुआ था, जहाँ लोग इस कहानी को हाइलाइट करके और प्रतिक्रिया देकर बातचीत जारी रख रहे हैं।

अस्वीकरण: इस साइट पर बाहर से पोस्ट किए गए लेख, सार्वजनिक प्लेटफार्म से लिए गए हैं और केवल सूचना देने के उद्देश्यों के लिए उपलब्ध कराए गए हैं. वे निश्चित तौर पर MEXC के विचारों को नहीं दिखाते. सभी संबंधित अधिकार मूल लेखकों के पास ही हैं. अगर आपको लगता है कि कोई कॉन्टेंट तीसरे पक्ष के अधिकारों का उल्लंघन करता है, तो कृपया उसे हटाने के लिए crypto.news@mexc.com से संपर्क करें. MEXC किसी कॉन्टेंट की सटीकता, पूर्णता या समयबद्धता के संबंध में कोई गारंटी नहीं देता है और प्रदान की गई जानकारी के आधार पर की गई किसी भी कार्रवाई के लिए जिम्मेदार नहीं है. यह कॉन्टेंट वित्तीय, कानूनी या अन्य प्रोफ़ेशनल सलाह नहीं है, न ही इसे MEXC द्वारा अनुशंसा या समर्थन माना जाना चाहिए.

आपको यह भी पसंद आ सकता है

Binance की डीलिस्टिंग का असर: 6 Altcoins एक्सचेंज से हटते ही क्रैश

Binance की डीलिस्टिंग का असर: 6 Altcoins एक्सचेंज से हटते ही क्रैश

Binance ने 23 अप्रैल को छह टोकन्स को डीलिस्ट करने की घोषणा की है, जिससे इन एसेट्स में तुरंत गिरावट आ गई। यह exchange अपने सभी स्पॉट ट्रेडिंग पेयर्स से Beefy.Fin
शेयर करें
Beincrypto HI2026/04/09 15:49
USD/INR: रेंज जोखिम और तेल संवेदनशीलता – MUFG

USD/INR: रेंज जोखिम और तेल संवेदनशीलता – MUFG

USD/INR: रेंज जोखिम और तेल संवेदनशीलता – MUFG पोस्ट BitcoinEthereumNews.com पर दिखाई दी। MUFG के वरिष्ठ मुद्रा विश्लेषक माइकल वान को उम्मीद है कि USD/INR स्थिर रहेगा
शेयर करें
BitcoinEthereumNews2026/04/09 15:38
ईरान ने कथित तौर पर टैंकरों से होर्मुज जलडमरूमध्य टोल बिटकॉइन में भुगतान करने को कहा

ईरान ने कथित तौर पर टैंकरों से होर्मुज जलडमरूमध्य टोल बिटकॉइन में भुगतान करने को कहा

होर्मुज जलडमरूमध्य से जुड़े एक रिपोर्ट किए गए निर्देश में कहा गया है कि तेल टैंकरों को बिटकॉइन में प्रति बैरल $1 का टोल देना होगा। भुगतान संरचना को डिज़ाइन किया गया प्रतीत होता है
शेयर करें
Crypto News Flash2026/04/09 15:08

24/7 लाइव न्यूज़

अधिक

$30,000 in PRL + 15,000 USDT

$30,000 in PRL + 15,000 USDT$30,000 in PRL + 15,000 USDT

Deposit & trade PRL to boost your rewards!