Echidna

# Echidna

Exemplos de fuzzing com Echidna (opens new window).

  1. Salve o contrato de solidity como TestEchidna.sol
  2. Na pasta onde seu contrato está armazenado execute o seguinte comando.
docker run -it --rm -v $PWD:/code trailofbits/eth-security-toolbox
  1. Veja os comentários abaixo e execute echidna-test comandos.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

/*
echidna-test TestEchidna.sol --contract TestCounter
*/
contract Counter {
    uint public count;

    function inc() external {
        count += 1;
    }

    function dec() external {
        count -= 1;
    }
}

contract TestCounter is Counter {
    function echidna_test_true() public view returns (bool) {
        return true;
    }

    function echidna_test_false() public view returns (bool) {
        return false;
    }

    function echidna_test_count() public view returns (bool) {
      // Aqui estamos testando que Counter.count deve sempre ser <= 5.
      // O teste falhará. Echidna é inteligente o suficiente para chamar Counter.inc() mais
      // do que 5 vezes.
        return count <= 5;
    }
}

/*
echidna-test TestEchidna.sol --contract TestAssert --check-asserts
*/
contract TestAssert {
    // Asserts não detectadas em 0.8.
    // Muda para 0.7 para testar asserções

    function test_assert(uint _i) external {
        assert(_i < 10);
    }

    // Exemplo mais complexo
    function abs(uint x, uint y) private pure returns (uint) {
        if (x >= y) {
            return x - y;
        }
        return y - x;
    }

    function test_abs(uint x, uint y) external {
        uint z = abs(x, y);
        if (x >= y) {
            assert(z <= x);
        } else {
            assert(z <= y);
        }
    }
}

# Tempo de teste e remetente

Echidna pode fuzz timestamp. O intervalo do timestamp é definido na configuração. O padrão é 7 dias.

callers de contrato também podem ser definidos na configuração. As contas padrão são

  • 0x10000
  • 0x20000
  • 0x00a329C0648769a73afAC7F9381e08fb43DBEA70
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;

/*
docker run -it --rm -v $PWD:/code trailofbits/eth-security-toolbox
echidna-test EchidnaTestTimeAndCaller.sol --contract EchidnaTestTimeAndCaller
*/
contract EchidnaTestTimeAndCaller {
    bool private pass = true;
    uint private createdAt = block.timestamp;

    /*
      teste falhará se Echidna puder chamar setFail()
      teste vai passar caso contrário
    */
    function echidna_test_pass() public view returns (bool) {
        return pass;
    }

    function setFail() external {
        /*
          Echidna pode chamar esta função se delay <= max block delay
          Caso contrário, o Echidna não poderá chamar esta função.
          O atraso máximo do bloco pode ser estendido especificando-o em um arquivo de configuração.
        */
        uint delay = 7 days;
        require(block.timestamp >= createdAt + delay);
        pass = false;
    }

    // Remetentes padrão
    // Altere os endereços para ver o teste falhar
    address[3] private senders = [
        address(0x10000),
        address(0x20000),
        address(0x00a329C0648769a73afAC7F9381e08fb43DBEA70)
    ];

    address private sender = msg.sender;

    //Passe _sender como entrada e exija msg.sender == _sender
    //para ver _sender para exemplo de contador

    function setSender(address _sender) external {
        require(_sender == msg.sender);
        sender = msg.sender;
    }

    // Verifique os remetentes padrão. O remetente deve ser uma das 3 contas padrão.
    function echidna_test_sender() public view returns (bool) {
        for (uint i; i < 3; i++) {
            if (sender == senders[i]) {
                return true;
            }
        }
        return false;
    }
}

# Teste no Remix

Last Updated: 15/10/2022 15:09:37