nascentxyz / simple-security-toolkit

A collection of practical security-focused guides and checklists for smart contract development
MIT License
1.07k stars 143 forks source link

Add Fuzz Testing Examples in Docs #4

Closed ElliotFriedman closed 1 year ago

ElliotFriedman commented 2 years ago

Examples of fuzz tests I've found helpful: https://github.com/fei-protocol/flywheel-v2/blob/main/src/test/FlywheelTest.sol https://github.com/fei-protocol/flywheel-v2/blob/main/src/test/token/ERC20GaugesTest.t.sol

JorgeAtPaladin commented 2 years ago

In our experience echidna tends to be a much stronger fuzzer compared to the build-in fuzzer that is used by Forge/dapptools.

Echidna uses slither to symbolically find all potential inputs

contract HelloWorld {
    function hello(string memory who) public pure returns (string memory) {
        if (compare(who, "Marco") == 0) { // compare code left out, it's a string comparison method that can be solved by a symbolic solver
            return "Meh";
        }
        return string(abi.encodePacked("Hello, ", who, "."));
    }

    function testStringMatch(string calldata str) external view returns (bool) {
        assert (keccak256(abi.encodePacked(hello(str))) == keccak256(abi.encodePacked(string.concat("Hello, ",       string(abi.encodePacked(str)), "."))));
    }
}

Echidna almost instantly proposes Marco as an input here while Forge is absolutely blind to it (even if you move the input of hello to an int, Forge will only find obvious matches like "1" due to it not using symbolic analysis.

We recommend to use echidna in assertion breaking mode most usually. The detection rate is much higher than Forge and when using the assertion mode the developer UX is not too much worse than Forge.