Skip to content

Latest commit

 

History

History
54 lines (45 loc) · 2.93 KB

AritmeticOverflowUnderflow.md

File metadata and controls

54 lines (45 loc) · 2.93 KB

Arithmetic Overflow and Underflow

One of the most common vulnerability found in Smart Contract is the overflow and underflow problem. In modern high-level programming languages like JavaScript or Python it's not anymore a problem, but in others like C++ or Solidity this problem exists.

An overflow occurs when a variable is incremented above its maximum value, resulting in the minimum number representable.

  0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ 0x000000000000000000000000000000000001
----------------------------------------
= 0x000000000000000000000000000000000000 

An underflow happens when an unsigned number is decremented below zero, resulting in the maximum possible value.

  0x000000000000000000000000000000000000
- 0x000000000000000000000000000000000001
----------------------------------------
= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

Integers in the Ethereum Virtual Machine have a specified size that determines the range of values they can represent: for example the type uint8 can only represent numbers between 0 and 255, if we try to store the value 256 in an uint8 variable it will result 0.

If variables and calculations are not checked it's possible to make a contract perform operations it shouldn't do through unexpected logic flows.

Example: Long-term fund

contract TimeLock {
    
    mapping(address => uint) public balances;
    mapping(address => uint) public lockTime;
    
    function deposit() public payable {
        balances[msg.sender] += msg.value;
        lockTime[msg.sender] = now + 10 years;
    }
    
    function increaseLockTime(uint _secondsToIncrease) public {
        lockTime[msg.sender] += _secondsToIncrease;
    }
    
    function withdraw() public {
        require(balances[msg.sender] > 0);
        require(now > lockTime[msg.sender]);
        msg.sender.transfer(balances[msg.sender]);
        balances[msg.sender] = 0;
    }
}

This contract stores your ether for at least 10 years from when the Ethers were received. By looking at the contract code it's possible to notice that there is no check on the value provided in the increaseLockTime function that influence the lockTime of the funds: it's a simple addition without any overflow check. lockTime value is an uint256, so its maximum value is 2^256. If we call the increaseLockTime function and give 2^256 - 1 as a parameter the lockTime variable will contain a value less that now, so the current timestamp. It's then possible to simply call the withdraw function and obtain the ether deposited.

Mitigation

OpenZeppelin create a collection of libraries for secure smart contract development that contains the SafeMath library, very useful for doing math operations without overflow and underflow problems. With Solidity 0.8 the error was solved by throwing and error when an overflow or underflow happens.