

Echidna एक अजीब प्राणी है जो बग्स खाती है और अत्यधिक इलेक्ट्रोसेंसिटिव है (Jacob Stanley से क्षमा के साथ)
अधिक गंभीरता से, Echidna एक Haskell प्रोग्राम है जिसे Ethereum स्मार्ट कॉन्ट्रैक्ट्स के फ़ज़िंग/प्रॉपर्टी-आधारित परीक्षण के लिए डिज़ाइन किया गया है। यह उपयोगकर्ता-परिभाषित प्रेडिकेट्स या Solidity assertions को गलत साबित करने के लिए contract ABI पर आधारित परिष्कृत व्याकरण-आधारित फ़ज़िंग अभियानों का उपयोग करता है। हमने Echidna को मॉड्यूलरिटी को ध्यान में रखते हुए डिज़ाइन किया है, इसलिए इसे नए म्यूटेशन शामिल करने या विशिष्ट मामलों में विशिष्ट कॉन्ट्रैक्ट्स का परीक्षण करने के लिए आसानी से विस्तारित किया जा सकता है।
.. और एक सुंदर उच्च-रिज़ॉल्यूशन हस्तनिर्मित लोगो।
Echidna की मुख्य कार्यक्षमता echidna नामक एक निष्पादन योग्य फ़ाइल है, जो एक कॉन्ट्रैक्ट और इनवेरिएंट्स (ऐसे गुण जो हमेशा सत्य रहने चाहिए) की सूची को इनपुट के रूप में लेती है। प्रत्येक इनवेरिएंट के लिए, यह कॉन्ट्रैक्ट को कॉल करने के यादृच्छिक अनुक्रम उत्पन्न करती है और जाँचती है कि इनवेरिएंट कायम है या नहीं। यदि यह इनवेरिएंट को गलत साबित करने का कोई तरीका खोज सकती है, तो यह उस कॉल अनुक्रम को प्रिंट करती है जो ऐसा करता है। यदि यह नहीं कर सकती, तो आपको कुछ आश्वासन मिलता है कि कॉन्ट्रैक्ट सुरक्षित है।
इनवेरिएंट्स को Solidity फ़ंक्शन्स के रूप में व्यक्त किया जाता है जिनके नाम echidna_ से शुरू होते हैं, कोई आर्ग्युमेंट नहीं लेते, और एक बूलियन लौटाते हैं। उदाहरण के लिए, यदि आपके पास कोई balance वेरिएबल है जो कभी भी 20 से नीचे नहीं जाना चाहिए, तो आप अपने कॉन्ट्रैक्ट में इस तरह एक अतिरिक्त फ़ंक्शन लिख सकते हैं:```solidity
function echidna_check_balance() public returns (bool) {
return(balance >= 20);
}
इन invariants को जाँचने के लिए, चलाएँ:```sh
$ echidna myContract.sol
एक उदाहरण अनुबंध जिसमें परीक्षण हैं, tests/solidity/basic/flags.sol पर पाया जा सकता है। इसे चलाने के लिए, आपको निष्पादित करना चाहिए:```sh $ echidna tests/solidity/basic/flags.sol
Echidna को एक कॉल अनुक्रम खोजना चाहिए जो `echidna_sometimesfalse` को गलत साबित करता है और `echidna_alwaystrue` के लिए गलत साबित करने वाला इनपुट खोजने में असमर्थ होना चाहिए।
### परीक्षण मोड
ऊपर दिया गया उदाहरण डिफ़ॉल्ट **property** मोड का उपयोग करता है, लेकिन Echidna कई परीक्षण मोड का समर्थन करता है, जिन्हें कॉन्फ़िग फ़ाइल में `testMode` या CLI पर `--test-mode` के माध्यम से कॉन्फ़िगर किया जाता है:
* **`property`** (डिफ़ॉल्ट): `echidna_`-उपसर्ग वाले फ़ंक्शन का परीक्षण करें जो `bool` लौटाते हैं।
* **`assertion`**: `assert()` और Foundry के `assertX` हेल्पर्स (`assertTrue`, `assertEq`, आदि) से assertion विफलताओं का पता लगाएं।
* **`foundry`**: Foundry-शैली के परीक्षण चलाएं, इसकी नामकरण परंपराओं का पालन करते हुए: `test`-उपसर्ग वाले यूनिट और फ़ज़ परीक्षण (`testFail`-उपसर्ग वाले revert होने की अपेक्षा की जाती है) और `invariant`- या `statefulFuzz`-उपसर्ग वाले stateful invariants। `check`- और `prove`-उपसर्ग वाले फ़ंक्शन प्रतीकात्मक प्रवेश बिंदु हैं, लेकिन चूंकि यह मोड एक फ़ज़िंग अभियान है, उन्हें किसी भी अन्य परीक्षण फ़ंक्शन की तरह फ़ज़ किया जाता है।
* **`verification`**: एकल लेनदेन का उपयोग करके अनुबंध के प्रत्येक फ़ंक्शन को प्रतीकात्मक रूप से सत्यापित करें। `check`- और `prove`-उपसर्ग वाले फ़ंक्शन हमेशा प्रवेश बिंदु के रूप में उपयोग किए जाते हैं।
* **`overflow`**: पूर्णांक over/underflows का पता लगाएं (Solidity >= 0.8.0)।
* **`optimization`**: `echidna_`-उपसर्ग वाले फ़ंक्शन का रिटर्न मान अधिकतम करें जो `int256` लौटाते हैं (property मोड के समान कॉन्फ़िगर करने योग्य उपसर्ग का उपयोग करता है)।
* **`exploration`**: गुणों की जांच किए बिना कवरेज एकत्र करें।
### कवरेज एकत्र करना और देखना
अभियान समाप्त करने के बाद, Echidna `corpusDir` कॉन्फ़िग विकल्प के साथ निर्दिष्ट एक विशेष निर्देशिका में कवरेज अधिकतम करने वाला **corpus** सहेज सकता है। इस निर्देशिका में दो प्रविष्टियाँ होंगी: (1) `coverage` नाम की एक निर्देशिका जिसमें JSON फ़ाइलें होंगी जिन्हें Echidna द्वारा फिर से चलाया जा सकता है और (2) `covered.txt` नाम की एक सादा-पाठ फ़ाइल, जो कवरेज एनोटेशन के साथ स्रोत कोड की एक प्रति है।
यदि आप `tests/solidity/basic/flags.sol` उदाहरण चलाते हैं, तो Echidna `coverage` निर्देशिका में कुछ फ़ाइलों में क्रमबद्ध लेनदेन और निम्नलिखित पंक्तियों के साथ एक `covered.$(date +%s).txt` फ़ाइल सहेजेगा:```text
*r | function set0(int val) public returns (bool){
* | if (val % 100 == 0)
* | flag0 = false;
}
*r | function set1(int val) public returns (bool){
* | if (val % 10 == 0 && !flag0)
* | flag1 = false;
}
हमारा टूल कॉर्पस में प्रत्येक निष्पादन ट्रेस को निम्नलिखित "लाइन मार्कर" के साथ चिह्नित करता है:
* यदि कोई निष्पादन STOP के साथ समाप्त हुआr यदि कोई निष्पादन REVERT के साथ समाप्त हुआo यदि कोई निष्पादन out-of-gas त्रुटि के साथ समाप्त हुआe यदि कोई निष्पादन किसी अन्य त्रुटि (शून्य विभाजन, assertion विफलता, आदि) के साथ समाप्त हुआEchidna विभिन्न स्मार्ट कॉन्ट्रैक्ट बिल्ड सिस्टम के साथ संकलित कॉन्ट्रैक्ट्स का परीक्षण कर सकता है, जिनमें Foundry, Hardhat, और Truffle शामिल हैं, crytic-compile का उपयोग करके। वर्तमान संकलन फ्रेमवर्क के साथ Echidna को आमंत्रित करने के लिए, echidna . का उपयोग करें।
इसके अतिरिक्त, Echidna जटिल कॉन्ट्रैक्ट्स के परीक्षण के दो मोड का समर्थन करता है। पहला, कोई व्यक्ति मौजूदा नेटवर्क स्थिति का लाभ उठा सकता है और उसे Echidna के लिए आधार स्थिति के रूप में उपयोग कर सकता है। दूसरा, Echidna CLI में संबंधित Solidity स्रोत पास करके किसी भी ज्ञात ABI वाले कॉन्ट्रैक्ट को कॉल कर सकता है। इसे सक्षम करने के लिए अपने कॉन्फ़िग में allContracts: true का उपयोग करें।
हमारे Building Secure Smart Contracts रिपॉजिटरी में Echidna पर एक क्रैश कोर्स है, जिसमें उदाहरण, पाठ और अभ्यास शामिल हैं।
एक Echidna एक्शन है जिसका उपयोग GitHub Actions वर्कफ़्लो के भाग के रूप में echidna चलाने के लिए किया जा सकता है। उपयोग निर्देशों और उदाहरणों के लिए कृपया crytic/echidna-action रिपॉजिटरी देखें।