How to Debug Ethereum Smart Contracts?
By: Abhishek Sharma
Tags: Blockchain, ICO, Ethereum, Dapps, Smart Contracts

Debugging a transaction in blockchain is different from debugging a traditional application build on C++ or JavaScript as you are not running a code in real time, instead in blockchain a historic transaction execution is mapped with associate code to debug a transaction.

A Smart contract is a piece of code run on the top of blockchain, smart contracts needs to make sense in precise manner, debugging a Smart contract is analyzing a transaction step by step how functions internally work and proceed or where the actual transaction has failed.

Lets discuss first about types of error in solidity in detail to debug transaction.

Types of Error in solidity —

1. Syntax Error

A syntax error arise when there is a problem in a syntax of smart contract code, when your code strike with syntax error your smart contract will not be able to compiled or deployed on blockchain.

Syntax error can be easily diagnosed using remix, as you can see in picture below, when semicolon(;) is removed from above code in remix IDE, it displays an error message with solution of syntax error.

Syntax error can be easily diagnosed using truffle, remix or any IDE.

2. Run time Error

Run time errors arises only when you have deployed a smart contract to blockchain and your solidity code has been compiled to bytecode that has been understood by EVM (Ethereum virtual machine). EVM is defined as a component of Ethereum that runs solidity code and run time error arises when EVM thinks that you are doing something wrong with your smart contract code or you are making transaction against the logic of the code.

Run time errors are more difficult to diagnose than syntax error because these errors are not identified before deploying on blockchain, they can only arise when state change take place in smart contract, we will discuss more about run time errors and debugging of run time errors in details.

3. Logic Errors

Logic errors cannot be debug using any IDE or tool, because logic errors are not captured by EVM, according to EVM everything is perfect and code can be run easily. logic error arise when developer make a mistake and open loop holes in a smart contract for attackers.

Example of Logic Error : Famous DAO attack(Reentrancy) is an example of logic error where developer made a mistake and transferred ether before updating balance of user.

Logical errors can be identified by Audit of smart contract because sometimes according to developer’s mindset everything is going well and there may not be an error in smart contract but an Auditor can run a smart contract with intent to find loop holes, check business logic and to find security flaws in smart contract.

Formal Verification may come into use for logic verification of smart contract.

Types of Run time error

Out of Gas

Out of gas error occurs when you don’t provide enough gas to execute a transaction, or gas is not enough to complete a transaction.

Revert

Transaction revert will occur when you are trying to execute a transaction that cannot be executed according to the logic of smart contract hence EVM will return an error and transaction is reverted.

Invalid opcode

Invalid opcode occur when you are trying to call a code that doesn’t exist.

invalid Jump

Invalid jump occur when you are trying to call a function that doesn’t exist, for example if you call a function of contract via another contract that doesn’t exist, invalid jump occurs. This type of error also occur when you use assembly language and you point to wrong memory.

Stack Overflow

Stack Overflow occurs when you are trying to call function recursively and there is no condition to stop it, in solidity stack can be at most 1024 frame, so a function can call itself only 1024x times, if you exceed that stack Overflow will occur.

Stack Underflow

Stack underflow occurs in assembly language when you try to pop a variable that doesn’t exist.

Sample Smart Contract code to be used in debugging all types of errors and transactions-

pragma solidity 0.4.24; contract Sample { uint256 public amountInContract; address public amountOwner; constructor(address _owner) public payable { require(_owner != address(0)); require(msg.value > 0.1 ether); amountInContract = msg.value; amountOwner = _owner; } function () external{ revert(); } function withdraw () public { require(msg.sender==amountOwner); msg.sender.transfer(address(this).balance); } }

The debugger provides the ability to debug any transaction (creation or call) step by step and to visualize the memory/storage space. It helps to trace the gas cost by opcode and the remaining gas after each step.

Debugging a transaction-

In above code as specified constructor is payable, while deploying a contract constructor required sending ether value above 0.1 ethers. If less than 0.1 ether is sent or address is zero, it will throw an error and transaction will be reverted.

As shown below, transaction is reverted so we will debug a transaction step by step using remix IDE.

Step 1. After deployment transaction is submitted to Ethereum blockchain using remix, transaction is failed as shown above. Now press the debugger button in remix IDE to debug the transaction and to find out the possible reason for transaction failure.

Step 2. To start debugging, provide block number and transaction hash and press the start debugging button this will start the debugging process.

Assembly language operations along with gas used and remaining gas is displayed while debugging a transaction as shown above, also code is highlighted in remix IDE where actual transaction failed parallel to opcode as shown below.

Transaction is reverted in assembly opcode. The code is highlighted where actual transaction reverted.

As shown in above picture where transaction is reverted in etherscan the value sent is 0.1 ether, that is less than the required value; that is why transaction failed in this scenario.

This process can be used to debug any transaction to know more about gas used, remaining gas at each step, state changes and to visualize memory/storage space.

Smart contract debugging can also be done using truffle framework, you need a transaction hash to debug a transaction.