Latest & Breaking Cryptocurrency, Blockchain, Ethereum, Bitcoin News- Coinedict
How-to's

How to audit a Smart Contract? A Complete Beginners Guide

How to audit a Smart Contract?

Smart Contract: Why is it important to audit them?

While the advent of blockchain technology has provided a unique opportunity for distributed consensus, smart contract applications come with a unique set of concerns. It is was not long ago that the infamous DAO attack led to millions of Dollars in losses. Hence, it is imperative to audit smart contracts. A smart contract audit is similar to a regular code audit. It involves scrupulously investigating the code to find plausible security flaws and vulnerabilities before deploying the code publicily. Since blockchain is a replicated, append-only linked “list” of Merkle trees and smart contracts are self-executing, it is critical to find any loopholes in the code before launch.

Types of Smart Contract Attacks

Race Conditions

It is a condition in which the events do not take place in the intended order. These conditions may arise from external contracts that take over control flow.

Video Courtesy: Youtube

Reentrancy

It is when one function is called repeatedly even before the first function invocation is completed. For instance, one of the DAO attacks was due to different invocations of functions interacting in unintended ways. The solution is to block concurrent calls from taking place in certain functions. It is all the more important to scrutinize external calls.

Example of a contract with the reentrancy bug:

contract ReentrancyVulnerability {
function withdraw () {
uint transferAmount = 10 ether;
if (!msg.sender.call.value(transferAmount)()) throw;
}
function deposit() payable {} // make contract payable and send ether
}

The line highlighted in red is an external call. It should be avoided. The function withdraw() transfers either to msg.sender. However, the receiver can call the function multiple times with a recursive send exploit. Suppose,  the above contract is in a ReentrancyVulnerability.sol file and the attacker creates a Hacker.sol file with a Hacker contract, exploiting the external call.

Such a contract may be used to test potential reentrancy loopholes:

contract Hacker {
ReentrancyVulnerability r;
uint public count;
event LogFallback(uint c, uint balance);
function Attacker(address vulnerable) {
r = ReentrancyVulnerability(vulnerable);
}
function attack() {
r.withdraw();
}
function () payable {
       count++;

  logFallback(count, this.balance);

       if (count < 10) {

         r.withdraw();

       }

}

Also Read: How to mine Ethereum?

Functions defined in Hacker Sol

  • Withdraw function as payable() – It calls the ReentrancyVulnerability contract withdraw() method and sends 10 ether to Hacker.
  • LogFallback(uint v, uint balance); This event is run through an if statement with a counter to act as a loop that stops the function at 10 calls to prevent ether reversion. Then, the Hacker’s withdraw() method is called again. This is possible because before the original withdraw() method in payable() is finished, withdraw() is called again until the if statement is satisfied last and the counter condition is met.

Reentry is merely a symptom and not the actual problem. Thus, it is important to analyse where the external functions are being used. One should not attempt to stop reentry directly at the function.

For instance, an attacker externally calls  transfer() before the user balance has been set to 0 :

function transfer(address to, uint amount)

{

 transfer occurs here
}
function withdrawBalance() public {

       uint amountToWithdraw = userBalances[msg.sender];

       require(msg.sender.call.value(amountToWithdraw)());        

userBalances[msg.sender] = 0;

}

In the above code, the hacker may call transfer() when the red line in withdrawBalance() is executed, or when the external call is made. The userBalance is only set to 0 afterwards, the hacker can transfer the tokens even though the withdrawal has been made.

Front Running

Front Running allows one user to benefit from a manipulated transaction order at the expense of another user. A condition that allows front running is timestamp dependence. One must carefully analyze the uses of the timestamp. It is especially more important in cases where transaction time is important, such as in a betting contract

Another set of conditions include  as integer overflow and underflow. In this, a unit value reaching the maximum circles to zero or a uint value less than zero gets set to its maximum. Tools such as Mythril can detect overflows and underflows.

uint public c = a + b;

c -= 2**2561;

}

function overflow() public {

c += 2**2561;

}

Note: Any code with the following logic is a vulnerability for the above:

require(this.balance > 0); // note that 0 could be any number

In order to prevent such attacks , the auditing process should be rigorous with a background of theory and practice, as well as tool application.

                                                                                      Video Courtesy: Youtube

Steps to conduct a full Smart Contract Audit

First, ensure that audit will be completed on a deployed smart contact. The audit should be performed on a release candidate (RC) as it is closest to the end-user product. Secondly, it is important to note that the purpose of the audit is to look for possible loopholes rather than to provide any guarantees.

The auditor can put a disclaimer at the end of the smart contract. For example: “The information appearing in this audit is for general discussion purposes only and is not intended to provide legal security guarantees to any individual or entity.”

Establishing Credibility

It is important for an auditor to explain his/her authority in the space. The auditor can use a rigorous analysis to back his/her claim.

Explaining the Audit Process

The auditor should then list the smart contracts he/she will audit and the process he/she will use.

Conducting Attack Vulnerability Tests:

It is important to analyze whether any of the attacks can be successfully carried out against the contract.

Listing Vulnerabilities

The auditor can list down vulnerabilities along with suggestions for fixes. There might be possible areas which do not require immediate attention but are a potential point of concern.

Analyzing Contract Complexity

A complex program will likely increase errors. The auditor must make note of complex contract logic, proprietary tools and code, non-modularized code and performance over clarity.

Analyzing Failure Preparation

The auditor must make a note on how would the contract would respond in the event of failures. Ensure that the contract pauses in such a case and there is provision for risk management.

Analyzing  Code Currency

Ensure that all libraries and tools have the latest updates.

Looking for any Re-used and  Duplicated Codes

A duplicated code from previous security proven contracts does not require an extensive analysis. The auditor should not use any code which has not been audited previously if a sound and previously deployed version is available.

Analyzing  External Calls

  • It is important to verify if state changes after external calls are avoided. This is done because external calls may manipulate control flow. It is important to complete all internal calls first.
  • Mark all the external contracts.  This is to convey that these code interactions are potentially unsafe.
  • If in case an exception is encountered, contract calls will propagate a throw.  It is important to note that without handling this, the contract will fail.
  • Ensure that external calls are isolated into their own transactions to minimize the consequences of external call failure.
  • There should be no initial balance assumption as a contract address may receive wei before the contract is created.
  • It should be ensured that the time at which certain on-chain data appears is not crucial to the contract functionality, as this data is public and the wrong order could favour one party over another.
  • Lastly, suggest any fixes to possible loopholes and in steps moving forward.

The ConsenSys Best Practices framework offers many “good and bad code” examples, which cover known attacks.

pragma solidity ^0.4.4; // bad

pragma solidity ^0.4.4; // good

For example, In order to avoid contracts getting deployed for another version lock pragmas to a specific compiler version.

uint256 constant private salt =  block.timestamp; // warning

Many decentralised applications have implemented several tools to aid in the auditing practice. An auditor can use these tools as a supplement but they cannot replace the formal auditing process.

Tools used in Smart Contract Auditing?

  1. Mythril- used for detecting uint overflows and underflows.
  2. Etherscrape- used to scrape live Ethereum contracts for reentrancy bugs .
  3. Bountyone- A decentralized auditing platform which brings together companies and freelance auditors when tools aren’t enough.

 

One can incorporate the above-mentioned tools and rigorously audit a smart contract. Lastly, the auditor may also add a point of contact for questions

Related posts

How to Buy Bitcoin in the Philippines 2020 Update

Sharukh Khan

A Simple Bitcoin Trading Guide for Beginners (2020 Updated) by PrimeXBT

Sharukh Khan

A Guide To How Trading Bots Work

Coinedict Team