---
title: "स्मार्ट अनुबंधों का परीक्षण करने के लिए एकिड्ना (Echidna) का उपयोग कैसे करें"
description: "स्मार्ट अनुबंधों का स्वचालित रूप से परीक्षण करने के लिए एकिड्ना का उपयोग कैसे करें"
author: "Trailofbits"
lang: hi
tags: ["Solidity", "स्मार्ट अनुबंध", "सुरक्षा", "परीक्षण", "फ़ज़िंग"]
skill: advanced
breadcrumb: "एकिड्ना"
published: 2020-04-10
source: Building secure contracts
sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/echidna
---

## इंस्टॉलेशन {#installation}

एकिड्ना को Docker के माध्यम से या पूर्व-संकलित (pre-compiled) बाइनरी का उपयोग करके इंस्टॉल किया जा सकता है।

### Docker के माध्यम से एकिड्ना {#echidna-through-docker}

```bash
docker pull trailofbits/eth-security-toolbox
docker run -it -v "$PWD":/home/training trailofbits/eth-security-toolbox
```

_अंतिम कमांड एक Docker में eth-security-toolbox चलाता है जिसकी पहुंच आपकी वर्तमान डायरेक्टरी तक होती है। आप अपने होस्ट से फ़ाइलें बदल सकते हैं, और Docker से फ़ाइलों पर टूल चला सकते हैं_

Docker के अंदर, चलाएं:

```bash
solc-select 0.5.11
cd /home/training
```

### बाइनरी {#binary}

[https://github.com/crytic/echidna/releases/tag/v1.4.0.0](https://github.com/crytic/echidna/releases/tag/v1.4.0.0)

## प्रॉपर्टी-आधारित फ़ज़िंग का परिचय {#introduction-to-property-based-fuzzing}

एकिड्ना एक प्रॉपर्टी-आधारित फ़ज़र है, जिसका वर्णन हमने अपने पिछले ब्लॉगपोस्ट ([1](https://blog.trailofbits.com/2018/03/09/echidna-a-smart-fuzzer-for-ethereum/), [2](https://blog.trailofbits.com/2018/05/03/state-machine-testing-with-echidna/), [3](https://blog.trailofbits.com/2020/03/30/an-echidna-for-all-seasons/)) में किया है।

### फ़ज़िंग {#fuzzing}

सुरक्षा समुदाय में [फ़ज़िंग](https://wikipedia.org/wiki/Fuzzing) एक प्रसिद्ध तकनीक है। इसमें प्रोग्राम में बग खोजने के लिए ऐसे इनपुट उत्पन्न करना शामिल है जो कमोबेश यादृच्छिक (random) होते हैं। पारंपरिक सॉफ़्टवेयर के लिए फ़ज़र (जैसे [AFL](http://lcamtuf.coredump.cx/afl/) या [LibFuzzer](https://llvm.org/docs/LibFuzzer.html)) बग खोजने के लिए कुशल टूल माने जाते हैं।

इनपुट के विशुद्ध रूप से यादृच्छिक निर्माण के अलावा, अच्छे इनपुट उत्पन्न करने के लिए कई तकनीकें और रणनीतियां हैं, जिनमें शामिल हैं:

- प्रत्येक निष्पादन (execution) से फीडबैक प्राप्त करना और उसका उपयोग करके निर्माण का मार्गदर्शन करना। उदाहरण के लिए, यदि कोई नया उत्पन्न इनपुट किसी नए पथ की खोज की ओर ले जाता है, तो उसके करीब नए इनपुट उत्पन्न करना समझदारी हो सकती है।
- संरचनात्मक बाधा (structural constraint) का सम्मान करते हुए इनपुट उत्पन्न करना। उदाहरण के लिए, यदि आपके इनपुट में चेकसम के साथ एक हेडर है, तो फ़ज़र को चेकसम को मान्य करने वाला इनपुट उत्पन्न करने देना उचित होगा।
- नए इनपुट उत्पन्न करने के लिए ज्ञात इनपुट का उपयोग करना: यदि आपके पास मान्य इनपुट के एक बड़े डेटासेट तक पहुंच है, तो आपका फ़ज़र शुरुआत से निर्माण करने के बजाय उनसे नए इनपुट उत्पन्न कर सकता है। इन्हें आमतौर पर _सीड्स (seeds)_ कहा जाता है।

### प्रॉपर्टी-आधारित फ़ज़िंग {#property-based-fuzzing}

एकिड्ना फ़ज़र के एक विशिष्ट परिवार से संबंधित है: प्रॉपर्टी-आधारित फ़ज़िंग जो [QuickCheck](https://wikipedia.org/wiki/QuickCheck) से काफी प्रेरित है। क्लासिक फ़ज़र के विपरीत जो क्रैश खोजने का प्रयास करेगा, एकिड्ना उपयोगकर्ता-परिभाषित इनवेरिएंट्स (invariants) को तोड़ने का प्रयास करेगा।

स्मार्ट अनुबंधों में, इनवेरिएंट्स Solidity फ़ंक्शन होते हैं, जो किसी भी गलत या अमान्य स्थिति का प्रतिनिधित्व कर सकते हैं जहां अनुबंध पहुंच सकता है, जिनमें शामिल हैं:

- गलत एक्सेस कंट्रोल: हमलावर अनुबंध का मालिक बन गया।
- गलत स्थिति मशीन: अनुबंध के रुके (paused) होने पर भी टोकन ट्रांसफर किए जा सकते हैं।
- गलत अंकगणित: उपयोगकर्ता अपने बैलेंस को अंडरफ़्लो कर सकता है और असीमित मुफ्त टोकन प्राप्त कर सकता है।

### एकिड्ना के साथ प्रॉपर्टी का परीक्षण करना {#testing-a-property-with-echidna}

हम देखेंगे कि एकिड्ना के साथ स्मार्ट अनुबंध का परीक्षण कैसे करें। लक्ष्य निम्नलिखित स्मार्ट अनुबंध [`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol) है:

```solidity
contract Token{
  mapping(address => uint) public balances;
  function airdrop() public{
      balances[msg.sender] = 1000;
  }
  function consume() public{
      require(balances[msg.sender]>0);
      balances[msg.sender] -= 1;
  }
  function backdoor() public{
      balances[msg.sender] += 1;
  }
}
```

हम यह मानकर चलेंगे कि इस टोकन में निम्नलिखित प्रॉपर्टीज़ होनी चाहिए:

- किसी के पास भी अधिकतम 1000 टोकन हो सकते हैं
- टोकन को ट्रांसफर नहीं किया जा सकता (यह ERC-20 टोकन नहीं है)

### एक प्रॉपर्टी लिखें {#write-a-property}

एकिड्ना प्रॉपर्टीज़ Solidity फ़ंक्शन हैं। एक प्रॉपर्टी में यह होना चाहिए:

- कोई तर्क (argument) न हो
- यदि यह सफल होता है तो `true` लौटाएं
- इसका नाम `echidna` से शुरू होना चाहिए

एकिड्ना करेगा:

- प्रॉपर्टी का परीक्षण करने के लिए स्वचालित रूप से मनमाने लेन-देन उत्पन्न करेगा।
- किसी भी ऐसे लेन-देन की रिपोर्ट करेगा जिसके कारण प्रॉपर्टी `false` लौटाती है या कोई त्रुटि (error) फेंकती है।
- प्रॉपर्टी को कॉल करते समय साइड-इफेक्ट को छोड़ देगा (यानी, यदि प्रॉपर्टी किसी स्थिति चर (state variable) को बदलती है, तो परीक्षण के बाद इसे छोड़ दिया जाता है)

निम्नलिखित प्रॉपर्टी जांचती है कि कॉलर के पास 1000 से अधिक टोकन नहीं हैं:

```solidity
function echidna_balance_under_1000() public view returns(bool){
      return balances[msg.sender] <= 1000;
}
```

अपने अनुबंध को अपनी प्रॉपर्टीज़ से अलग करने के लिए इनहेरिटेंस (inheritance) का उपयोग करें:

```solidity
contract TestToken is Token{
      function echidna_balance_under_1000() public view returns(bool){
            return balances[msg.sender] <= 1000;
      }
  }
```

[`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol) प्रॉपर्टी को लागू करता है और टोकन से इनहेरिट करता है।

### अनुबंध प्रारंभ करें {#initiate-a-contract}

एकिड्ना को बिना तर्क वाले [कंस्ट्रक्टर](/developers/docs/smart-contracts/anatomy/#constructor-functions) की आवश्यकता होती है। यदि आपके अनुबंध को एक विशिष्ट इनिशियलाइज़ेशन की आवश्यकता है, तो आपको इसे कंस्ट्रक्टर में करना होगा।

एकिड्ना में कुछ विशिष्ट पते (addresses) हैं:

- `0x00a329c0648769A73afAc7F9381E08FB43dBEA72` जो कंस्ट्रक्टर को कॉल करता है।
- `0x10000`, `0x20000`, और `0x00a329C0648769a73afAC7F9381e08fb43DBEA70` जो यादृच्छिक रूप से अन्य फ़ंक्शंस को कॉल करते हैं।

हमें अपने वर्तमान उदाहरण में किसी विशेष इनिशियलाइज़ेशन की आवश्यकता नहीं है, परिणामस्वरूप हमारा कंस्ट्रक्टर खाली है।

### एकिड्ना चलाएं {#run-echidna}

एकिड्ना को इसके साथ लॉन्च किया जाता है:

```bash
echidna-test contract.sol
```

यदि contract.sol में कई अनुबंध हैं, तो आप लक्ष्य निर्दिष्ट कर सकते हैं:

```bash
echidna-test contract.sol --contract MyContract
```

### सारांश: प्रॉपर्टी का परीक्षण {#summary-testing-a-property}

निम्नलिखित हमारे उदाहरण पर एकिड्ना के रन का सारांश देता है:

```solidity
contract TestToken is Token{
    constructor() public {}
        function echidna_balance_under_1000() public view returns(bool){
          return balances[msg.sender] <= 1000;
        }
  }
```

```bash
echidna-test testtoken.sol --contract TestToken
...

echidna_balance_under_1000: failed!💥
  Call sequence, shrinking (1205/5000):
    airdrop()
    backdoor()

...
```

एकिड्ना ने पाया कि यदि `backdoor` को कॉल किया जाता है तो प्रॉपर्टी का उल्लंघन होता है।

## फ़ज़िंग अभियान के दौरान कॉल करने के लिए फ़ंक्शंस को फ़िल्टर करना {#filtering-functions-to-call-during-a-fuzzing-campaign}

हम देखेंगे कि फ़ज़ किए जाने वाले फ़ंक्शंस को कैसे फ़िल्टर किया जाए।
लक्ष्य निम्नलिखित स्मार्ट अनुबंध है:

```solidity
contract C {
  bool state1 = false;
  bool state2 = false;
  bool state3 = false;
  bool state4 = false;

  function f(uint x) public {
    require(x == 12);
    state1 = true;
  }

  function g(uint x) public {
    require(state1);
    require(x == 8);
    state2 = true;
  }

  function h(uint x) public {
    require(state2);
    require(x == 42);
    state3 = true;
  }

 function i() public {
    require(state3);
    state4 = true;
  }

  function reset1() public {
    state1 = false;
    state2 = false;
    state3 = false;
    return;
  }

  function reset2() public {
    state1 = false;
    state2 = false;
    state3 = false;
    return;
  }

  function echidna_state4() public returns (bool) {
    return (!state4);
  }
}
```

यह छोटा उदाहरण एकिड्ना को स्थिति चर को बदलने के लिए लेन-देन का एक निश्चित क्रम खोजने के लिए मजबूर करता है।
यह एक फ़ज़र के लिए कठिन है (यह अनुशंसा की जाती है कि [मैन्टिकोर](https://github.com/trailofbits/manticore) जैसे सिम्बोलिक निष्पादन टूल का उपयोग करें)।
हम इसे सत्यापित करने के लिए एकिड्ना चला सकते हैं:

```bash
echidna-test multi.sol
...
echidna_state4: passed! 🎉
Seed: -3684648582249875403
```

### फ़ंक्शंस को फ़िल्टर करना {#filtering-functions}

एकिड्ना को इस अनुबंध का परीक्षण करने के लिए सही क्रम खोजने में परेशानी होती है क्योंकि दो रीसेट फ़ंक्शन (`reset1` और `reset2`) सभी स्थिति चरों को `false` पर सेट कर देंगे।
हालाँकि, हम रीसेट फ़ंक्शन को ब्लैकलिस्ट करने या केवल `f`, `g`,
`h` और `i` फ़ंक्शंस को व्हाइटलिस्ट करने के लिए एक विशेष एकिड्ना सुविधा का उपयोग कर सकते हैं।

फ़ंक्शंस को ब्लैकलिस्ट करने के लिए, हम इस कॉन्फ़िगरेशन फ़ाइल का उपयोग कर सकते हैं:

```yaml
filterBlacklist: true
filterFunctions: ["reset1", "reset2"]
```

फ़ंक्शंस को फ़िल्टर करने का एक अन्य तरीका व्हाइटलिस्ट किए गए फ़ंक्शंस को सूचीबद्ध करना है। ऐसा करने के लिए, हम इस कॉन्फ़िगरेशन फ़ाइल का उपयोग कर सकते हैं:

```yaml
filterBlacklist: false
filterFunctions: ["f", "g", "h", "i"]
```

- `filterBlacklist` डिफ़ॉल्ट रूप से `true` है।
- फ़िल्टरिंग केवल नाम से (बिना पैरामीटर के) की जाएगी। यदि आपके पास `f()` और `f(uint256)` हैं, तो फ़िल्टर `"f"` दोनों फ़ंक्शंस से मेल खाएगा।

### एकिड्ना चलाएं {#run-echidna-1}

कॉन्फ़िगरेशन फ़ाइल `blacklist.yaml` के साथ एकिड्ना चलाने के लिए:

```bash
echidna-test multi.sol --config blacklist.yaml
...
echidna_state4: failed!💥
  Call sequence:
    f(12)
    g(8)
    h(42)
    i()
```

एकिड्ना लगभग तुरंत ही प्रॉपर्टी को गलत साबित करने के लिए लेन-देन का क्रम खोज लेगा।

### सारांश: फ़ंक्शंस को फ़िल्टर करना {#summary-filtering-functions}

एकिड्ना फ़ज़िंग अभियान के दौरान कॉल करने के लिए फ़ंक्शंस को ब्लैकलिस्ट या व्हाइटलिस्ट कर सकता है, इसका उपयोग करके:

```yaml
filterBlacklist: true
filterFunctions: ["f1", "f2", "f3"]
```

```bash
echidna-test contract.sol --config config.yaml
...
```

एकिड्ना `filterBlacklist` बूलियन के मान के अनुसार, या तो `f1`, `f2` और `f3` को ब्लैकलिस्ट करके या केवल इन्हें कॉल करके फ़ज़िंग अभियान शुरू करता है।

## एकिड्ना के साथ Solidity के दावे (assert) का परीक्षण कैसे करें {#how-to-test-soliditys-assert-with-echidna}

इस छोटे ट्यूटोरियल में, हम यह दिखाने जा रहे हैं कि अनुबंधों में दावा (assertion) जांच का परीक्षण करने के लिए एकिड्ना का उपयोग कैसे करें। मान लीजिए कि हमारे पास इस तरह का एक अनुबंध है:

```solidity
contract Incrementor {
  uint private counter = 2**200;

  function inc(uint val) public returns (uint){
    uint tmp = counter;
    counter += val;
    // tmp <= counter
    return (counter - tmp);
  }
}
```

### एक दावा (assertion) लिखें {#write-an-assertion}

हम यह सुनिश्चित करना चाहते हैं कि इसका अंतर लौटाने के बाद `tmp`, `counter` से कम या उसके बराबर हो। हम एक एकिड्ना प्रॉपर्टी लिख सकते हैं, लेकिन हमें `tmp` मान को कहीं स्टोर करने की आवश्यकता होगी। इसके बजाय, हम इस तरह के दावे का उपयोग कर सकते हैं:

```solidity
contract Incrementor {
  uint private counter = 2**200;

  function inc(uint val) public returns (uint){
    uint tmp = counter;
    counter += val;
    assert (tmp <= counter);
    return (counter - tmp);
  }
}
```

### एकिड्ना चलाएं {#run-echidna-2}

दावा विफलता परीक्षण को सक्षम करने के लिए, एक [एकिड्ना कॉन्फ़िगरेशन फ़ाइल](https://github.com/crytic/echidna/wiki/Config) `config.yaml` बनाएं:

```yaml
checkAsserts: true
```

जब हम इस अनुबंध को एकिड्ना में चलाते हैं, तो हमें अपेक्षित परिणाम प्राप्त होते हैं:

```bash
echidna-test assert.sol --config config.yaml
Analyzing contract: assert.sol:Incrementor
assertion in inc: failed!💥
  Call sequence, shrinking (2596/5000):
    inc(21711016731996786641919559689128982722488122124807605757398297001483711807488)
    inc(7237005577332262213973186563042994240829374041602535252466099000494570602496)
    inc(86844066927987146567678238756515930889952488499230423029593188005934847229952)

Seed: 1806480648350826486
```

जैसा कि आप देख सकते हैं, एकिड्ना `inc` फ़ंक्शन में कुछ दावा विफलता की रिपोर्ट करता है। प्रति फ़ंक्शन एक से अधिक दावे जोड़ना संभव है, लेकिन एकिड्ना यह नहीं बता सकता कि कौन सा दावा विफल रहा।

### दावों का उपयोग कब और कैसे करें {#when-and-how-use-assertions}

दावों का उपयोग स्पष्ट प्रॉपर्टीज़ के विकल्प के रूप में किया जा सकता है, विशेष रूप से यदि जांच की जाने वाली शर्तें सीधे किसी ऑपरेशन `f` के सही उपयोग से संबंधित हैं। कुछ कोड के बाद दावे जोड़ने से यह लागू होगा कि इसके निष्पादित होने के तुरंत बाद जांच होगी:

```solidity
function f(..) public {
    // कुछ जटिल कोड
    ...
    assert (condition);
    ...
}

```

इसके विपरीत, एक स्पष्ट एकिड्ना प्रॉपर्टी का उपयोग करने से लेन-देन यादृच्छिक रूप से निष्पादित होंगे और यह लागू करने का कोई आसान तरीका नहीं है कि इसकी जांच कब की जाएगी। यह वर्कअराउंड करना अभी भी संभव है:

```solidity
function echidna_assert_after_f() public returns (bool) {
    f(..);
    return(condition);
}
```

हालाँकि, कुछ समस्याएं हैं:

- यह विफल हो जाता है यदि `f` को `internal` या `external` के रूप划 में घोषित किया गया है।
- यह स्पष्ट नहीं है कि `f` को कॉल करने के लिए किन तर्कों का उपयोग किया जाना चाहिए।
- यदि `f` रिवर्ट होता है, तो प्रॉपर्टी विफल हो जाएगी।

सामान्य तौर पर, हम दावों का उपयोग करने के तरीके पर [John Regehr की अनुशंसा](https://blog.regehr.org/archives/1091) का पालन करने की सलाह देते हैं:

- दावा जांच के दौरान किसी भी साइड इफेक्ट को मजबूर न करें। उदाहरण के लिए: `assert(ChangeStateAndReturn() == 1)`
- स्पष्ट कथनों का दावा न करें। उदाहरण के लिए `assert(var >= 0)` जहां `var` को `uint` के रूप में घोषित किया गया है।

अंत में, कृपया `assert` के बजाय `require` का **उपयोग न करें**, क्योंकि एकिड्ना इसका पता लगाने में सक्षम नहीं होगा (लेकिन अनुबंध वैसे भी रिवर्ट हो जाएगा)।

### सारांश: दावा जांच {#summary-assertion-checking}

निम्नलिखित हमारे उदाहरण पर एकिड्ना के रन का सारांश देता है:

```solidity
contract Incrementor {
  uint private counter = 2**200;

  function inc(uint val) public returns (uint){
    uint tmp = counter;
    counter += val;
    assert (tmp <= counter);
    return (counter - tmp);
  }
}
```

```bash
echidna-test assert.sol --config config.yaml
Analyzing contract: assert.sol:Incrementor
assertion in inc: failed!💥
  Call sequence, shrinking (2596/5000):
    inc(21711016731996786641919559689128982722488122124807605757398297001483711807488)
    inc(7237005577332262213973186563042994240829374041602535252466099000494570602496)
    inc(86844066927987146567678238756515930889952488499230423029593188005934847229952)

Seed: 1806480648350826486
```

एकिड्ना ने पाया कि `inc` में दावा विफल हो सकता है यदि इस फ़ंक्शन को बड़े तर्कों के साथ कई बार कॉल किया जाता है।

## एकिड्ना कॉर्पस (corpus) एकत्र करना और संशोधित करना {#collecting-and-modifying-an-echidna-corpus}

हम देखेंगे कि एकिड्ना के साथ लेन-देन का कॉर्पस कैसे एकत्र करें और उसका उपयोग कैसे करें। लक्ष्य निम्नलिखित स्मार्ट अनुबंध [`magic.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/magic.sol) है:

```solidity
contract C {
  bool value_found = false;
  function magic(uint magic_1, uint magic_2, uint magic_3, uint magic_4) public {
    require(magic_1 == 42);
    require(magic_2 == 129);
    require(magic_3 == magic_4+333);
    value_found = true;
    return;
  }

  function echidna_magic_values() public returns (bool) {
    return !value_found;
  }

}
```

यह छोटा उदाहरण एकिड्ना को स्थिति चर को बदलने के लिए कुछ मान खोजने के लिए मजबूर करता है। यह एक फ़ज़र के लिए कठिन है
(यह अनुशंसा की जाती है कि [मैन्टिकोर](https://github.com/trailofbits/manticore) जैसे सिम्बोलिक निष्पादन टूल का उपयोग करें)।
हम इसे सत्यापित करने के लिए एकिड्ना चला सकते हैं:

```bash
echidna-test magic.sol
...

echidna_magic_values: passed! 🎉

Seed: 2221503356319272685
```

हालाँकि, हम अभी भी इस फ़ज़िंग अभियान को चलाते समय कॉर्पस एकत्र करने के लिए एकिड्ना का उपयोग कर सकते हैं।

### कॉर्पस एकत्र करना {#collecting-a-corpus}

कॉर्पस संग्रह को सक्षम करने के लिए, एक कॉर्पस डायरेक्टरी बनाएं:

```bash
mkdir corpus-magic
```

और एक [एकिड्ना कॉन्फ़िगरेशन फ़ाइल](https://github.com/crytic/echidna/wiki/Config) `config.yaml`:

```yaml
coverage: true
corpusDir: "corpus-magic"
```

अब हम अपना टूल चला सकते हैं और एकत्र किए गए कॉर्पस की जांच कर सकते हैं:

```bash
echidna-test magic.sol --config config.yaml
```

एकिड्ना अभी भी सही मैजिक मान नहीं खोज सकता है, लेकिन हम इसके द्वारा एकत्र किए गए कॉर्पस पर एक नज़र डाल सकते हैं।
उदाहरण के लिए, इनमें से एक फ़ाइल थी:

```json
[
  {
    "_gas'": "0xffffffff",
    "_delay": ["0x13647", "0xccf6"],
    "_src": "00a329c0648769a73afac7f9381e08fb43dbea70",
    "_dst": "00a329c0648769a73afac7f9381e08fb43dbea72",
    "_value": "0x0",
    "_call": {
      "tag": "SolCall",
      "contents": [
        "magic",
        [
          {
            "contents": [
              256,
              "93723985220345906694500679277863898678726808528711107336895287282192244575836"
            ],
            "tag": "AbiUInt"
          },
          {
            "contents": [256, "334"],
            "tag": "AbiUInt"
          },
          {
            "contents": [
              256,
              "68093943901352437066264791224433559271778087297543421781073458233697135179558"
            ],
            "tag": "AbiUInt"
          },
          {
            "tag": "AbiUInt",
            "contents": [256, "332"]
          }
        ]
      ]
    },
    "_gasprice'": "0xa904461f1"
  }
]
```

स्पष्ट रूप से, यह इनपुट हमारी प्रॉपर्टी में विफलता को ट्रिगर नहीं करेगा। हालाँकि, अगले चरण में, हम देखेंगे कि इसके लिए इसे कैसे संशोधित किया जाए।

### कॉर्पस को सीड (seed) करना {#seeding-a-corpus}

एकिड्ना को `magic` फ़ंक्शन से निपटने के लिए कुछ मदद की आवश्यकता है। हम इसके लिए उपयुक्त मापदंडों का उपयोग करने के लिए इनपुट को कॉपी और संशोधित करने जा रहे हैं:

```bash
cp corpus/2712688662897926208.txt corpus/new.txt
```

हम `magic(42,129,333,0)` को कॉल करने के लिए `new.txt` को संशोधित करेंगे। अब, हम एकिड्ना को फिर से चला सकते हैं:

```bash
echidna-test magic.sol --config config.yaml
...
echidna_magic_values: failed!💥
  Call sequence:
    magic(42,129,333,0)


Unique instructions: 142
Unique codehashes: 1
Seed: -7293830866560616537

```

इस बार, इसने पाया कि प्रॉपर्टी का तुरंत उल्लंघन हो गया है।

## उच्च गैस खपत वाले लेन-देन खोजना {#finding-transactions-with-high-gas-consumption}

हम देखेंगे कि एकिड्ना के साथ उच्च गैस खपत वाले लेन-देन कैसे खोजें। लक्ष्य निम्नलिखित स्मार्ट अनुबंध है:

```solidity
contract C {
  uint state;

  function expensive(uint8 times) internal {
    for(uint8 i=0; i < times; i++)
      state = state + i;
  }

  function f(uint x, uint y, uint8 times) public {
    if (x == 42 && y == 123)
      expensive(times);
    else
      state = 0;
  }

  function echidna_test() public returns (bool) {
    return true;
  }

}
```

यहां `expensive` में गैस की खपत अधिक हो सकती है।

वर्तमान में, एकिड्ना को परीक्षण के लिए हमेशा एक प्रॉपर्टी की आवश्यकता होती है: यहां `echidna_test` हमेशा `true` लौटाता है।
हम इसे सत्यापित करने के लिए एकिड्ना चला सकते हैं:

```
echidna-test gas.sol
...
echidna_test: passed! 🎉

Seed: 2320549945714142710
```

### गैस खपत मापना {#measuring-gas-consumption}

एकिड्ना के साथ गैस खपत को सक्षम करने के लिए, एक कॉन्फ़िगरेशन फ़ाइल `config.yaml` बनाएं:

```yaml
estimateGas: true
```

इस उदाहरण में, हम परिणामों को समझने में आसान बनाने के लिए लेन-देन अनुक्रम के आकार को भी कम करेंगे:

```yaml
seqLen: 2
estimateGas: true
```

### एकिड्ना चलाएं {#run-echidna-3}

एक बार जब हम कॉन्फ़िगरेशन फ़ाइल बना लेते हैं, तो हम एकिड्ना को इस तरह चला सकते हैं:

```bash
echidna-test gas.sol --config config.yaml
...
echidna_test: passed! 🎉

f used a maximum of 1333608 gas
  Call sequence:
    f(42,123,249) Gas price: 0x10d5733f0a Time delay: 0x495e5 Block delay: 0x88b2

Unique instructions: 157
Unique codehashes: 1
Seed: -325611019680165325

```

- दिखाई गई गैस [HEVM](https://github.com/dapphub/dapptools/tree/master/src/hevm#hevm-) द्वारा प्रदान किया गया एक अनुमान है।

### गैस कम करने वाले कॉल्स को फ़िल्टर करना {#filtering-out-gas-reducing-calls}

ऊपर **फ़ज़िंग अभियान के दौरान कॉल करने के लिए फ़ंक्शंस को फ़िल्टर करना** पर ट्यूटोरियल दिखाता है कि आपके परीक्षण से कुछ फ़ंक्शंस को कैसे हटाया जाए।  
सटीक गैस अनुमान प्राप्त करने के लिए यह महत्वपूर्ण हो सकता है।
निम्नलिखित उदाहरण पर विचार करें:

```solidity
contract C {
  address [] addrs;
  function push(address a) public {
    addrs.push(a);
  }
  function pop() public {
    addrs.pop();
  }
  function clear() public{
    addrs.length = 0;
  }
  function check() public{
    for(uint256 i = 0; i < addrs.length; i++)
      for(uint256 j = i+1; j < addrs.length; j++)
        if (addrs[i] == addrs[j])
          addrs[j] = address(0x0);
  }
  function echidna_test() public returns (bool) {
      return true;
  }
}
```

यदि एकिड्ना सभी फ़ंक्शंस को कॉल कर सकता है, तो यह आसानी से उच्च गैस लागत वाले लेन-देन नहीं खोज पाएगा:

```
echidna-test pushpop.sol --config config.yaml
...
pop used a maximum of 10746 gas
...
check used a maximum of 23730 gas
...
clear used a maximum of 35916 gas
...
push used a maximum of 40839 gas
```

ऐसा इसलिए है क्योंकि लागत `addrs` के आकार पर निर्भर करती है और यादृच्छिक कॉल्स एरे (array) को लगभग खाली छोड़ देते हैं।
हालाँकि, `pop` और `clear` को ब्लैकलिस्ट करने से हमें बहुत बेहतर परिणाम मिलते हैं:

```yaml
filterBlacklist: true
filterFunctions: ["pop", "clear"]
```

```
echidna-test pushpop.sol --config config.yaml
...
push used a maximum of 40839 gas
...
check used a maximum of 1484472 gas
```

### सारांश: उच्च गैस खपत वाले लेन-देन खोजना {#summary-finding-transactions-with-high-gas-consumption}

एकिड्ना `estimateGas` कॉन्फ़िगरेशन विकल्प का उपयोग करके उच्च गैस खपत वाले लेन-देन खोज सकता है:

```yaml
estimateGas: true
```

```bash
echidna-test contract.sol --config config.yaml
...
```

फ़ज़िंग अभियान समाप्त होने के बाद, एकिड्ना प्रत्येक फ़ंक्शन के लिए अधिकतम गैस खपत वाले अनुक्रम की रिपोर्ट करेगा।