# Variable inspection: Going deeper with the Truffle Solidity debugger

Note: This tutorial requires Truffle version 4.1.8 or newer.

The integrated Solidity debugger in Truffle is a powerful tool for inspecting your contracts.

When initially released, the debugger had the ability to to step through Solidity code, but that was it.

But development has continued apace, and new functionality has been added to make your contract inspection more powerful. Specifically, you now have the ability to perform variable inspection on your contracts. With this, you can know exactly the state of your variables at every given point in the instruction list, giving you a much greater ability to truly inhabit the current state of your contracts, and making debugging a breeze.

In this tutorial, we're going to take a look at a simple contract and inspect it using the Truffle Solidity debugger. We'll investigate three scenarios:

1. A working contract
2. A working contract with unexpected output
3. A broken contract

The Fibonacci sequence is an integer sequence where each successive number in the sequence is the sum of the two previous numbers.

With the first two numbers set to 1, you can determine every number in the sequence through iteration.

The Fibonacci sequence is related to the "golden ratio", which is found in certain areas of nature, such as governing the the arrangement of leaves on branches and petals on flowers. The golden ratio in nature: flower petals. (Source: Flickr)

Generating the Fibonacci sequence with a smart contract can show off the debugger and its variable inspection without getting too bogged down in details. Let's do it.

1. Create a new project directory called `fibonacci` and change into it.

``````mkdir fibonacci
cd fibonacci``````
2. Create a bare truffle project:

``truffle init``
3. In the `contracts/` directory, create a file named `Fibonacci.sol` and add the following content:

``````pragma solidity ^0.4.22;

contract Fibonacci {

uint[] fibseries;

// n = how many in the series to return
function generateFib(uint n) public {

// set 1st and 2nd entries
fibseries.push(1);
fibseries.push(1);

// generate subsequent entries
for (uint i=2; i < n ; i++) {
fibseries.push(fibseries[i-1] + fibseries[i-2]);
}

}

}``````

Let's take a look at this contract to see what's going on with it:

• First, we see the standard `pragma` declaration, which states that the contract s compatible with any 0.4.x version of Solidity newer than 0.4.22.
• The contract name is called `Fibonacci`.
• We're defining an array of integers called `fibseries`. This will house our Fibonacci series. Note that the variable declaration is happening outside of any function, and therefore the array will be saved in storage (instead of memory), provoking a transaction to occur when the contract is run.
• The function is called `generateFib` and takes a single argument, which is the number of integers in the sequence to generate.
• The next two commands add an element each to the array via the `.push()` method. As we know our `fibseries` array is defined in storage, but size isn't known until runtime, the `.push()` method is used to add entries to (the end of) our array. This starts the sequence with the number 1 twice.
• The for loop iterates through the rest of the array (as determined by the integer `n`) filling each entry with the appropriate value.
4. Inside the `migrations/` directory of your project, create a file called `2_deploy_contracts.js` and populate it with the following content:

``````var Fibonacci = artifacts.require("Fibonacci");

module.exports = function(deployer) {
deployer.deploy(Fibonacci);
};``````

This file allows us to deploy the `Fibonacci` contract (shown above) to the blockchain.

5. Now launch Ganache. This will be the personal blockchain we'll use to deploy our contract. Ganache

Note: You can also run this tutorial with [Truffle Develop](/docs/getting_started/console) and the results will be the same.

6. In the root of your project, open your `truffle.js` file and add the following content:

``````module.exports = {
networks: {
development: {
host: "127.0.0.1",
port: 7545,
network_id: "*"
}
}
};``````

This allows us to connect our project to Ganache.

7. Launch the Truffle console:

``truffle console``

You will see a prompt:

``truffle(development)>``

We'll run all of our commands from here.

8. Compile the contract:

``compile``

You should see the following output:

``````Compiling .\contracts\Fibonacci.sol...
Compiling .\contracts\Migrations.sol...
Writing artifacts to .\build\contracts``````

Note: Make sure to examine the output for any errors or warnings.

9. Migrate the contract to our blockchain.

``migrate``

You will see output that looks like this, though the addresses and transaction IDs will be different:

``````Using network 'development'.

Running migration: 1_initial_migration.js
Replacing Migrations...
... 0xd29465deee7a5d60aed89520807432ef8a2fbbb665611882277ec8ca6fc9c622
Migrations: 0x5cc77b19b8e14e4d6074562bdbe1e13e1b793693
Saving successful migration to network...
Saving artifacts...
Running migration: 2_deploy_contracts.js
Replacing Fibonacci...
... 0xed0d1b736e948d926ee31f959b013f67d71e08f294a87e86e41ccbd8a62ce908
Fibonacci: 0xa3f4063ffbdc5cfd8ecbd99424378a5f056eb81d
Saving successful migration to network...
... 0xcaeb44f5e28689c29cb3189c7b42fa1094021b4e5008f720fef2f9b867e6be23
Saving artifacts...``````

Our contract is now on the blockchain. Ganache has automatically mined the transactions that came from the contract call and creation, as you can see by clicking the "Transactions" button in Ganache: Ganache transactions

Now it's time to interact with the contract. First we'll check to make sure that it's working correctly.

1. In the Truffle console, enter the following command:

``Fibonacci.deployed().then(function(instance){return instance.generateFib(10);});``

Before we run the command, let's take a look at it in greater detail. Displayed in a more easily-readable manner, it reads:

``````Fibonacci.deployed().then(function(instance) {
return instance.generateFib(10);
});``````

This command uses JavaScript promises. Specifically, the command says that given a deployed version of the Fibonacci contract, run an instance of that contract, and then run the `generateFib` function from that contract, passing it the argument `10`.

2. Run the above command. A transaction will be created on the blockchain because our array that holds the generated Fibonacci sequence is in storage. Because of this, the output of the console will be the transaction details, which will look similar to this:

``````{ tx: '0xf47f01da1a6991f4dc168928cf4c490cb9bb57ca403b428f40a333ea65d1c41c',
receipt:
{ transactionHash: '0xf47f01da1a6991f4dc168928cf4c490cb9bb57ca403b428f40a333ea65d1c41c',
transactionIndex: 0,
blockHash: '0x88d45cb84d1f26001b0e7ae2931a56dfc0a592a1d0437fe0a37540d65f49a2ed',
blockNumber: 5,
gasUsed: 298373,
cumulativeGasUsed: 298373,
logs: [],
status: '0x01',
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' },
logs: [] }``````

The important part of this output for us is the transaction ID (listed as the value of `tx:`). Because even though we've run our function, we don't actually know what happened. Did it work correctly? Did something unexpected happen? We'll need the Truffle Solidity debugger to find out.

Note: Your transaction ID will be different from the above.

You can debug a transaction in the Truffle console by typing `debug <transactionID>`. We'll now do just that.

1. Type `debug` and then the value of `tx:` found in your transaction details. For example:

``debug 0xf47f01da1a6991f4dc168928cf4c490cb9bb57ca403b428f40a333ea65d1c41c``

Note: Your transaction ID will be different. Do not copy the above example exactly.

This will enter the debugger. You will see the following output:

``````Gathering transaction data...

0x33b217190208f7b8d2b14d7a30ec3de7bd722ac6 - Fibonacci

Commands:
(enter) last command entered (step next)
(o) step over, (i) step into, (u) step out, (n) step next
(;) step instruction, (p) print instruction, (h) print this help, (q) quit
(b) toggle breakpoint, (c) continue until breakpoint
(+) add watch expression (`+:<expr>`), (-) remove watch expression (-:<expr>)
(?) list existing watch expressions
(v) print variables and values, (:) evaluate expression - see `v`

Fibonacci.sol:

1: pragma solidity ^0.4.22;
2:
3: contract Fibonacci {
^^^^^^^^^^^^^^^^^^^^

debug(development:0xf47f01da...)>``````

Let's examine what's going on here.

• The debugger names the address of the contract in question that is related to the transaction, as well as the name of that contract. In our case, we're only dealing with a single contract, though if our transaction dealt with multiple contracts, all addresses would be shown.
• A full list of commands for the debugger is shown. Many of these mirror other code debuggers. We'll use a few of these throughout the tutorial, but if you ever want to see the list again, type `h`.
• The debugger starts at the first instruction of the transaction, and shows you the relevant code for that instruction, highlighted with carets (`^^^`).
2. Type `n` and `<Enter>` to step next. This will move to the next instruction:

``````6:
7:   // n = how many in the series to return
8:   function generateFib(uint n) public {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

debug(development:0xf47f01da...)>``````
3. We've seen in the previous tutorial on debugging how you can step through the instructions to debug your contract. But here, we have an additional concern, which is that we don't actually know the outcome of our function call; we want to know what a variable is set to. You can view the state of all known variables by pressing `v`:

``````  fibseries: []

debug(development:0xf47f01da...)>``````

Here we see one empty array. The arry `fibseries` will have the `n` numbers in the Fibonacci sequence.

4. Press `Enter` to repeat the last command, and step next to the next instruction:

`````` 9:
10:     // set 1st and 2nd entries
11:     fibseries.push(1);
^^^^^^^^^

debug(development:0xf47f01da...)>``````

This instruction moves on to the initial seeding of the `fibseries` variable.

5. Press `v` to see the current state of the variables:

``````          i: 0
n: 10
fibseries: []``````

Now we see three variables, our `fibseries` array and two others:

• `i` is an index variable, used to determine the location of the next number in the sequence
• `n` is the integer we passed to the function (`10` in this case) indicating the number of entries in our Fibonacci sequence

Here we see that `n` has been passed the value from the contract, while `i` hasn't received its value from the for loop yet, since we haven't gotten to that part of the function.

6. Press `Enter` to step next to the next instruction:

`````` 9:
10:     // set 1st and 2nd entries
11:     fibseries.push(1);
^``````
7. It's rather tedious to constantly press `v` after every state change. Thankfully, you can set certain variables to be "watched", so that they will display after every movement in the debugger. The syntax to watch a variable is `+:<variable>`. So let's watch the variables we care about (`i` and `fibseries`) with the following two commands:

``````+:i

+:fibseries``````

After each command, the current value of the variable will display. But once done, we'll get a persistent display of the variables and their values.

8. Press `Enter` to move to the next instruction:

`````` 9:
10:     // set 1st and 2nd entries
11:     fibseries.push(1);
^^^^^^^^^^^^^^^^^

:i
0

:fibseries
[]``````

Notice that after the current instruction, the watched variables are displayed automatically.

9. You can also watch expressions, not just variables. Run the following expression to make our output a little more compact.

``+:{ i, fibseries }``

This will output as follows:

``{ i: 0, fibseries: [] }``
10. Since we have all we need in this one expression, we can unwatch the individual variables. The syntax to watch a variable is `-:<variable>`.

``````-:i

-:fibseries``````

Now we'll only be watching the single expression comprising the two variables.

11. Press `Enter` to move to the next instruction and see the output:

``````10:     // set 1st and 2nd entries
11:     fibseries.push(1);
12:     fibseries.push(1);
^^^^^^^^^

:{ i, fibseries }
{ i: 0, fibseries: [ 1 ] }``````

Notice that we have now populated the first entry in the sequence.

12. Because the debugger steps through each instruction one at a time, it's going to take a long time to see results if we don't pick up our pace. Luckily, the debugger can "step over", which steps over the current line, moving to the next line, as long as it's at the same function depth. This will allow us to make progress much more quickly. So type `o` to step over the current instruction set. The output will be:

``````13:
14:     // generate subsequent entries
15:     for (uint i=2; i < n ; i++) {
^

:{ i, fibseries }
{ i: 0, fibseries: [ 1, 1 ] }``````

Here we see that we have populated the first two entries in the sequence.

13. Since `Enter` will replay the previous command, press `Enter` now to step over again:

``````14:     // generate subsequent entries
15:     for (uint i=2; i < n ; i++) {
16:       fibseries.push(fibseries[i-1] + fibseries[i-2]);
^^^^^^^^^

:{ i, fibseries }
{ i: 2, fibseries: [ 1, 1 ] }``````

Now that we have two entries in our sequence, we've moved into our for loop.

14. Continue pressing `Enter` and watching the variable output. You should notice that when `i` gets to `10`, the for loop ends (as the loop terminates at `i < n`). The final array is:

``[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]``

It can be verified that this is the correct first ten entries in the Fibonacci sequence.

Our contract as we have created it is working as expected. That's great, but we can't always get so lucky. Sometimes a contract appears to work fine (no errors are thrown) but the output is not what you'd expect. Let's examine that here.

It's amazing what switching a plus sign for a minus sign can do. Instead of the Fibonacci sequence:

``````F = 1
F = 1
F[n] = F[n-1] + F[n-2]``````

Let's switch the plus for a minus sign:

``````F = 1
F = 1
F[n] = F[n-1] - F[n-2]``````

(I don't know if this series has a name, so we'll just call it the "Trufflenacci" sequence.)

Let's edit our contract and see what happens.

1. Open the Fibonacci.sol file. Edit the definition of our `fibseries[]` array to be of type `uint8[]`.

``uint8[] fibseries;``

Note: A `uint8` is an unsigned integer with 8 bits, with a maximum value of 2^8 = 255. Compare this to a `uint`, which is a 256 bit number with a maximum value of 2^256.

2. Edit the for loop so that the terms are subtracted instead of added:

``fibseries.push(fibseries[i-1] - fibseries[i-2]);``
3. Save this file.

4. Back on the console, recompile the contract.

``compile --all``

Note: The `--all` flag with force recompile all of the contracts.

5. Remigrate the contract to the blockchain.

``migrate --reset``
6. We can now run the same command as before, which will generate a new transaction:

``Fibonacci.deployed().then(function(instance){return instance.generateFib(10);});``

As before, the output of the console will be the transaction details. Note the transaction hash (the value of `tx:`).

7. Type `debug` and then the value of `tx:` found in your transaction details. This will enter the debugger again.

``````Fibonacci.sol:

1: pragma solidity ^0.4.22;
2:
3: contract Fibonacci {
^^^^^^^^^^^^^^^^^^^^``````
8. We're curious about what our `fibseries` array is going to look like, so let's watch it:

``+:fibseries``

The response will be `undefined`, because we haven't yet gotten to the point in the code where that array was defined.

9. Let's "step over" execution, so as to speed things up ("step next" takes much longer, as it's a more granular process). You can "step over" by running the `o` command.

``````Fibonacci.sol:

6:
7:   // n = how many in the series to return
8:   function generateFib(uint n) public {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

:fibseries
[]``````

The array is defined, but is still empty.

10. Since `Enter` repeats the previous command (in our case, "step over"), press Enter twice. You'll see that the first element of `fibseries` has been populated.

``````10:     // set 1st and 2nd entries
11:     fibseries.push(1);
12:     fibseries.push(1);
^^^^^^^^^

:fibseries
[ 1 ]``````
11. Keep pressing Enter until four elements have been populated:

``````:fibseries
[ 1, 1, 0, 255 ]``````

Something seems off here. Obviously, if you were expecting the Fibonacci series, by this point you would realize that you had veered far off course.

But the jump from `0` to `255` should be suspicious too. And in fact, what we're seeing is a buffer underflow, a situation where we have an unsigned integer, which can hold only positive values, being set to less than zero. Specifically, that fourth value is defined as the difference between the previous two elements, so `0 - 1 = -1`. Our type is `uint8[]` which means that each integer in the array is defined by 8 bits, so its maximum value is 2^8 - 1 = 255. Subtract one from zero, and the value "wraps around" to its maximum value.

Assuming this was the series we wanted (and that our minus sign was correct), the way to change this is to change the definition of our `fibseries` array from `uint8[]` to `int8[]`. That would make values "signed integers" and able to accept negative values, giving you an array that would look like this instead:

``[ 1, 1, 0, -1 ]``

Sometimes, contracts have errors in them. They may compile just fine, but when you go to use them, problems arise.

This is one of the reasons to use Ganache over a public testnet: you can easily redeploy a contract without any penalty in time or ether.

So we're going to introduce a small error, a misnumbering in our for loop that will cause it to have an invalid index.

1. Open the `Fibonacci.sol` file again.

2. Edit the for loop so that the `i` variable starts from `1`

``for (uint i=1; i < n ; i++) {``
3. Save this file.

4. Back on the console, recompile the contract.

``compile --all``
5. Remigrate the contract to the blockchain.

``migrate --reset``
6. Run the same command as before:

``Fibonacci.deployed().then(function(instance){return instance.generateFib(10);});``

``Error: VM Exception while processing transaction: invalid opcode``

Well that's not good. Moreover, the output didn't give us a transaction ID to debug, so we're going to need to look elsewhere for it. Thankfully, Ganache can tell us the transaction information.

7. Go back in Ganache and click the "Logs" link at the top: Click this button to open the logs

8. At the very bottom of the logs, you will see a transaction ID listed near an error saying `invalid opcode`. This is the one we need. Copy this transaction ID. Ganache logs

9. Back in the console, type `debug` and paste in the transaction ID. This will enter the debugger again.

10. Let's watch the same compacted expression as before, showing both the value of `i` and the value of `fibseries`.

``+:{ i, fibseries }``
11. Continually step next. You will eventually reach a state where the debugger will error out.

``````14:     // generate subsequent entries
15:     for (uint i=1; i < n ; i++) {
16:       fibseries.push(fibseries[i-1] - fibseries[i-2]);
^^^^^^^^^^^^^^

:{ i, fibseries }
{ i: 1, fibseries: [ 1, 1 ] }

debug(development:0x948da9db...)>

Transaction halted with a RUNTIME ERROR.

This is likely due to an intentional halting expression, like assert(), require() or revert(). It can also be due to out-of-gas exceptions. Please inspect your transaction parameters and contract code to determine the meaning of this error.``````

Note that the contract is failing at the point where it tries to determine the value of `fibseries[i-2]` But in our debugger, we know that the current value of `i` is `1`, so `i-2` is going to be `-1` (or actually `2^256 - 1`, due to the buffer underflow issue we talked about above, and with `i` defined as a `uint`). Since either one of those values are invalid (you can't have a negative index, and the value at index `2^256 - 1` is clearly not defined), the contract halts with an error.

These are just some of the ways that you can use variable inspection to debug your contracts. We're constantly adding functionality of the debugger, so please raise an issue on our Github page or ask a fellow Truffler in our community Gitter channel. Happy debugging!