Debugging transactions in Ethereum. Part 2: Truffle and Buidler
Tags: ethereum, blockchain, solidity
Published: 2020-03-17 13:37:59

---
title: Debugging transactions in Ethereum. Part 2: Truffle and Buidler
published: true
description: Using truffle debugger and the buidler EVM for a better debugging experience
tags: ethereum,blockchain,solidity
---

In the [previous post](https://dev.to/fvictorio/debugging-transactions-in-ethereum-part-1-the-long-and-winding-road-c51) we looked at some ways to debug transactions that were mined in a testnet or in the mainnet, using [etherscan](http://etherscan.io/) and [eth-cli](https://github.com/protofire/eth-cli). In this post we'll move to transactions that we execute in "local" blockchains, like [ganache-cli](https://github.com/trufflesuite/ganache-cli) and the [Buidler EVM](https://buidler.dev/buidler-evm/).

I'm going to use the Truffle MetaCoin box for the examples, so if you want to follow along you can start by running `npx truffle unbox metacoin` in an empty directory. You'll also have to edit the `truffle-config.js` file, uncomment it, and change the port of the development network from 7545 to 8545.

## Truffle debug

If your project is built using [Truffle](https://www.trufflesuite.com/docs/truffle/overview), you can use its debugger to inspect a transaction step by step. This is a command line tool similar to `gdb` or `pdb`; if you've used something like that in the past, the experience is very similar.

In our example, if we start `ganache-cli` in another terminal and then run `npx truffle test`, we'll see a bunch of transactions being executed. Copy the hash of the last transaction and run:

```
npx truffle compile # this might be necessary if the build/ directory isn't there
npx truffle debug 0x3e3299b90e92efeccfe806f7b67e4683fb2c6ad2e114cbbe4b1308e4402ce090
```

(Your hash could be different.)

And you'll get something like this:

![Truffle debugger 1](https://dev-to-uploads.s3.amazonaws.com/i/4ro5006my2yyixljzzmf.png)

Here you can do things like seting a breakpoint with `b`, stepping over to the next line with `o` or evaluating an expression with `:`. Let's step over twice and inspect the value of the `amount` parameter with `:amount`:

![Truffle debugger 2](https://dev-to-uploads.s3.amazonaws.com/i/6zsmyvyxb5kvbpkn1tfu.png)

Check [the docs](https://www.trufflesuite.com/docs/truffle/getting-started/debugging-your-contracts) to learn more about this feature.

### Debugging tests

Another tool you can use is the global `debug()` function in your tests. Go to `test/metacoin.js` and replace this line

```diff
-const balance = await metaCoinInstance.getBalance.call(accounts[0]);
+const balance = await debug(metaCoinInstance.getBalance.call(accounts[0]));
```

and then run your tests with `npx truffle test --debug` (notice the extra flag). Your tests will be interrupted when that method is called and you'll be able to inspect it:

![Truffle debugger 3](https://dev-to-uploads.s3.amazonaws.com/i/cc07fxleyvvaf7tjue8v.png)

This is great not only because you don't need to get the hash of some transaction, but also because you can use it for plain calls that don't even send a transaction.

### Debugging non-local transactions

What about transactions in a testnet or in the mainnet? As far as I know, `truffle debug` can be used against any node that supports the `debug_traceTransaction` JSON-RPC method. And (again, AFAIK; here I am in the "I don't really know what I'm talking about" territory) besides local blockchains, this method is supported mainly by geth when syncing in archive mode. I haven't tested it because this requires syncing more than 2 TB of data.

Are there any other alternatives? Not that I'm aware of. [Infura](https://infura.io/) doesn't support `debug_traceTransaction` calls. I also tried using `ganache --fork` but this didn't work either (it actually kind of worked once? I think it might if the transaction is recent enough).

Anyway, if anyone knows how to do this, please let me know in the comments.

## Buidler

Buidler is a task runner for smart contract projects that comes with a lot of useful tools. You can use it on its own, or you can complement a truffle project with it, which is what we're going to do here. First, install it:

```
yarn add --dev @nomiclabs/buidler
```

and then run `npx buidler` and select the "Create an empty buidler.config.js" option.

### console.log

One of the things that come with Buidler is the Buidler EVM, that lets you do things like logging stuff inside your contracts or having stack traces that work across solidity and javascript. Let's start with the console.

First, open the `contracts/MetaCoin.sol` file and add these two lines:

```diff
 pragma solidity >=0.4.25 <0.7.0;

 import "./ConvertLib.sol";
+import "@nomiclabs/buidler/console.sol";

...

 	function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
+       console.log(msg.sender, receiver, amount);
 		if (balances[msg.sender] < amount) return false;
```

Next, kill `ganache-cli` (if it's still running) and execute `npx buidler node`, which starts a node that uses the Buidler EVM.

Now just run `npx truffle test` and you'll be able to see the console messages:

![Buidler 1](https://dev-to-uploads.s3.amazonaws.com/i/de014pmqqgs90apdjeu0.png)

You'll notice that here we are logging the same information that is emitted in the `Transfer` event, so what's the point? Well, first of all, events are not emitted for failed transactions, but the console works just fine. And second, you can also use logs for method calls that don't send transactions.

### Stack traces

The Buidler EVM also supports stack traces that look like this:

![Buidler 2](https://dev-to-uploads.s3.amazonaws.com/i/6nvdwqikkrglgqzi97xk.png)

As you can see, here we get both the line of the contract that failed, and the line of the javascript test that triggered the transaction!

Getting this to work is a little more involved, but worth it. First, install the truffle and web3 buidler plugins:

```
yarn add --dev @nomiclabs/buidler-truffle5 "@nomiclabs/buidler-web3@^1.2.0"
```

Then open `buidler.config.js` and add

```
usePlugin("@nomiclabs/buidler-truffle5")
```

to the beginning of the file.

Then create a file called `test/truffle-fixture.js`:

```js
const MetaCoin = artifacts.require("MetaCoin")
const ConvertLib = artifacts.require("ConvertLib")

module.exports = async () => {
  const convertLib = await ConvertLib.new()
  ConvertLib.setAsDeployed(convertLib)
  MetaCoin.link(convertLib)
  const metacoin = await MetaCoin.new()
  MetaCoin.setAsDeployed(metacoin)
}
```

This is just some glue code we need so that our contracts are deployed before running our tests with buidler (so far we've been running them with truffle).

You'll also need to remove the solidity test that comes with the MetaCoin box:

```
rm test/TestMetaCoin.sol
```

This is necessary because buidler doesn't support Solidity tests yet.

Now everything is ready: run `npx buidler test` to run your tests in the Buidler EVM. Of course, tests still pass so we won't get a stack trace. Let's modify our contract to trigger an error. Open `contracts/MetaCoin.sol` and add this line:

```diff
  ...

	function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
+       require(amount <= 5);
    ...
```

and run `npx buidler test` again. You'll get a stack trace like the one we saw at the beginning.

---

Both Truffle and Buidler offer some nice functionalities to help make sense of what's happening inside your contracts.  The `MetaCoin` contract is really simple, so this might seem overkill, but you've surely run into issues where you wished you'd had a debugger, a logger or a stack trace. Or, even better, all three of them!