DEV Community

Cover image for SC Auditing Tools - a quick overview
Priyanshu
Priyanshu

Posted on

SC Auditing Tools - a quick overview

TL;DR

This article is all about smart contract auditing tools. A smart contract audit entails a thorough examination of the contract's code to spot security flaws, improper, inefficient coding, and to decide how to fix the issues. In this article, we will take a look at some of the top smart contract auditing tools with a small demo

NOTE- Internal workings, architecture and advanced usage of all these tools can't be compiled in a single article, and for that I would work on single dedicated article for each of these tools.

Echidna

Echidna is a Haskell program designed for fuzzing/property-based testing of Ethereum smart contracts. It uses sophisticated grammar-based fuzzing campaigns based on a contract ABI to falsify user-defined predicates or Solidity assertions.
Fuzz testing or Fuzzing is the art of automatic bug detection. It is a Black Box software testing technique, which consists of finding implementation bugs using malformed/ semi-malformed data injection in an automated fashion.

In contrast to a classic fuzzer that will try to find crashes, Echidna will try to break user-defined invariants.

In smart contracts, invariants are Solidity functions, that can represent any incorrect or invalid state that the contract can reach, including:

  • Incorrect access control: the attacker became the owner of the contract.

  • Incorrect state machine: the tokens can be transferred while the contract is paused.

  • Incorrect arithmetic: the user can underflow its balance and get unlimited free tokens.

Demo

  1. For this demo we would be using a sample smart contract saved as Test.sol in any directory of your choice.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

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) {
        // Here we are testing that Counter.count should always be <= 5.

        return count <= 5;
    }
}

Enter fullscreen mode Exit fullscreen mode
  1. In the folder where your contract is stored execute the following command.
    docker run -it --rm -v $PWD:/code trailofbits/eth-security-toolbox

    Now inside docker, your code will be stored at /code. After running the above command cd /code.

  2. Now you are inside '/code' folder present in docker container and execute command echidna-test Test.sol --contract TestCounter. This command runs the tests written inside the Test.sol file and if we have multiple contracts, then we need to specify the contract name using the --contract tag.

NOTE- You can also select the desired compiler version by using the command solc-select use 'VERSION'

Image description

Image description

As we can see there were 3 tests and in any condition, if any of the tests return false then that test fails and Echidna also gives the transaction sequence due to which the test failed.

Slither

Slither is a Solidity static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses.

Features

  • Automated vulnerability detection. A large variety of smart contract bugs can be detected without user intervention or additional specification effort.

  • Automated optimization detection. Slither detects code optimizations that the compiler misses.

  • Code understanding. Slither summarizes and displays contracts’ information to aid your study of the codebase.

  • Assisted code review. A user can interact with Slither through its API.

Demo

Steps 1 and 2 are the same but for this demo we would be using a sample voting smart contract saved as test.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.8.9;

contract VotingSystem{

    struct Voter{

        bool alreadyVoted ;

        uint proposalIndex;
    }

    struct Proposal{

         string proposalName; 
        uint256 voteCount;
    }

    mapping(address => Voter) VoterAddress;

    Proposal[] private proposals;

        // input name of the proposal 
     function initialize(string memory name) public {

            proposals.push(Proposal(name,0));
     }

     // msg.sender can vote only once 
     // this function finds the proposal with the passed string in input 
     function voteTo(string memory _name) public {

         require(VoterAddress[msg.sender].alreadyVoted== false, "you have already voted");
         VoterAddress[msg.sender].alreadyVoted = true;
         for(uint i = 0;i<proposals.length;i++){

             if(keccak256(bytes(proposals[i].proposalName)) == keccak256(bytes(_name))){
                      VoterAddress[msg.sender].proposalIndex = i; 
                       proposals[i].voteCount++;
             }
         }
     }
     // this function returns who the winner is 
     function winner() view  public returns(string memory){

           uint max = 0;
           string memory winnerProposal;
           for(uint i = 0;i<proposals.length;i++){

               if(proposals[i].voteCount>max){
                   max  = proposals[i].voteCount;
                   winnerProposal = proposals[i].proposalName;
               }
           }
           return winnerProposal;
       }

}
Enter fullscreen mode Exit fullscreen mode

For the next step we just need to run the command slither test.sol

Image description

Image description

Here we can see the recommendations and vulnerabilities pointed out by slither.

Mythril

Developed as a part of the MythX security analysis suite by Consensys, Mythril is the dynamic smart contract security analysis component of this toolset. Mythril uses symbolic execution, SMT solving, and taint analysis to detect security vulnerabilities with contracts on any EVM-compatible chain.

The Mythril tool can be used for discovering vulnerabilities such as numeric overflow, owner overwrite, function re-run, etc.

The tool provides a fairly detailed and user-friendly audit report. This makes it easy to find the highlighted part of the code in the original file and manually check for potential vulnerabilities. Mythril cannot find ways to save gas.

Demo

  1. First step would be to create a vulnerable contract and save it as TimeLock.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;


contract TimeLock {
    mapping(address => uint) public balances;
    mapping(address => uint) public lockTime;

    function deposit() external payable {
        balances[msg.sender] += msg.value;
        lockTime[msg.sender] = block.timestamp + 1 weeks;
    }

    function increaseLockTime(uint _secondsToIncrease) public {
        lockTime[msg.sender] += _secondsToIncrease;
    }

    function withdraw() public {
        require(balances[msg.sender] > 0, "Insufficient funds");
        require(block.timestamp > lockTime[msg.sender], "Lock time not expired");

        uint amount = balances[msg.sender];
        balances[msg.sender] = 0;

        (bool sent, ) = msg.sender.call{value: amount}("");
        require(sent, "Failed to send Ether");
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Next step is to run the command docker run -v $(pwd):/code mythril/myth analyze /code/EtherStore.sol. This command mounts your code from the current directory inside your docker container, inside /code folder and runs the mythril analyze command as well.

Image description

There are many tools out there but these are the ones that I personally recommend & that's it for now folks.....adios

Top comments (0)