Skip to content

Latest commit

 

History

History
135 lines (99 loc) · 4.61 KB

integer_overflow.asciidoc

File metadata and controls

135 lines (99 loc) · 4.61 KB

Integer Overflow

UPDATE: My newer article, published on HackerNoon, which clears everything up. https://hackernoon.com/exploding-rockets-millions-of-free-tokens-lets-take-a-good-look-at-integer-overflows-2800794e48d9

Disclaimer: This information is based on my personal understanding of integer overflows in code. This document offers no advice nor opinions. This document has only been produced to exercise my personal understanding; it serves as a place to jot down my notes to prompt my thinking.

Testing multiplication of numbers

A Solidity Smart Contract code for multiplication might look something like this.

pragma solidity ^0.4.23;

/*
        Integer Overflow Testing v0.1
*/

contract IntegerOverflowTesting{
        string public version = "0.1";

        /**
        @dev    This function tests integer multiplication by allowing the caller to pass in any two uint256 integers
        @param  _a is a single uint256 integer value which is passed in by the function caller
        @param  _b is a single uint256 integer value which is passed in by the function caller
        @return This function returns a single uint256 integer value
        */
        function multiply(uint256 _a, uint256 _b) public pure returns(uint256 _c){
                _c = _a * _b;
                return _c;
        }
}

If I have two positive numbers 2 and 2 and I multiply them together I get 4

> deployedSmartTokenContract.multiply(2, 2)
4

Working with zeros

If any or both of the numbers passed in are zero then the answer will be zero

> deployedSmartTokenContract.multiply(0, 1)
0
> deployedSmartTokenContract.multiply(1, 0)
0
> deployedSmartTokenContract.multiply(0, 0)
0

Working with ones

Aside from when a zero is presented (as one of the inputs), if one of the inputs is "one" then the output should simply be the value of the other number which is passed in.

> deployedSmartTokenContract.multiply(1, 1)
1
> deployedSmartTokenContract.multiply(1, 2)
2
> deployedSmartTokenContract.multiply(1, 123456789)
123456789

Pushing the limits

The most that a uint256 variable should accept as input is 2²⁵⁶ -1. This number can be represented as a whole number like this

57896044618658097711785492504343953926634992332820282019728792003956564819968

Or in hexadecimal form like this

0x8000000000000000000000000000000000000000000000000000000000000000

If I pass either of these to the multiply function which I wrote above I will get the following output.

> deployedSmartTokenContract.multiply(1, 57896044618658097711785492504343953926634992332820282019728792003956564819968)
5.78960446186581e+76
> deployedSmartTokenContract.multiply(1, 0x8000000000000000000000000000000000000000000000000000000000000000)
5.78960446186581e+76

Hitting the limits

The system has the capability to refuse numbers bigger than this. For example if I pass 2 to the 257 -1 (instead of 2²⁵⁶ -1) the system will Error.

> deployedSmartTokenContract.multiply(1, 231584179999999997410779582514519949157839141792512746635478192824992309182464)
Error: invalid argument 0: json: cannot unmarshal hex string of odd length into Go struct field CallArgs.data of type hexutil.Bytes
    at web3-cmt.js:11472:20
    at web3-cmt.js:14605:15
    at web3-cmt.js:13390:36
    at web3-cmt.js:12415:22
    at apply (<native code>)
    at web3-cmt.js:12540:12
    at <anonymous>:1:1

The above error is more in relation to an invalid argument than the system’s inability to refuse uint256 numbers which are "to large".

Beyond the limits

So the system will not take a uint256 argument which is greater than 2²⁵⁶ -1.

Interestingly though, the following call to the multiply function demonstrates that a single allowable argument (2²⁵⁶ -1 or below) can be multiplied with another valid argument, say the number 2; the result will be saved to the uint256 variable _c in the multiply function. In fact, the multiply function will return the result as part of its successful execution.

> deployedSmartTokenContract.multiply(2, 57896044618658097711785492504343953926634992332820282019728792003956564819968)
0

I wrote an article on HackerNoon which goes into details about this and shows how CyberMiles prevents integer overflows.