Solidity has some fun gotcha moments.

Perhaps my favorite is documented in Liam Edwards-Playne’s compilation of awesome Solidity patterns: the untrustworthiness of var i = 0 .

In short: Solidity believes i to be a uint8 , which means it can only store the values 0 through 255 .

What if the condition in a for loop is 256 or greater?

Example: MurmurHash

Googling around GitHub repositories for Solidity code I ran into an interesting example that would work and pass test cases, but would fail once the incoming data was large enough.

This library calculates a non-crytographic lookup hash called MurmurHash.

function digest(bytes key, uint seed) returns (bytes32 _hash) {

//

// Compute and return a Murmur3 Hash.

// - https://en.wikipedia.org/wiki/MurmurHash

//

_hash = bytes32(seed);



// Compute how many 4-byte chunks are in `key`

uint numChunks = key.length / 4;



// Iterate over 4-byte chunks of `key`

for (var i = 0; i < numChunks; i ++) {

bytes32 k = 0;

bytes32 fourByteChunk = 0;

Note that key.length is divided by 4 and that result, numChunks is the conditional check in the for loop.

Since var i = 0 instances itself as a uint8 (which can only store a value up to 255) the loop will run infinitely for input of a key with a length of 1,024 or greater (which will result in a numChunk value of 256 or greater).

Running this code in Remix does indeed generate an infinite loop for largest enough key sizes.

Counter Example: instant-poker

On the other hand, one mitigation is to do conditional checks before the for loop even starts, like in the example of instant-poker.

assert(players.length <= 32);

uint256 val = uint256(value);

uint[] memory payments = new uint[](players.length);

for (var i = 0; i < players.length; i++) {

uint8 v = uint8(val & 255);

The assert at the beginning of this code block prevents a case where players.length can be greater than 255 .

Example Gist

Want to see it in action? Deploy this contract on Remix (memory) or your favorite testnet.

It’s sole purpose in life is to increment a variable and return it to you: it should be the exact same as the input you gave.

Note that Remix literally tells you this is a bad idea with two separate warnings:

var is deprecated

is deprecated var i = 0 instantiates as a uint8

Check out the test results, here’s a good example:

And here’s what happens when we try putting in a value like 256:

Summary