89DEVs

SafeMath in Solidity

safemath in solidity

SafeMath is obsolete in Solidity 0.8 and above because the overflow and underflow check is done on the language level within the Virtual Machine. Before Solidity 0.8 numbers overflowed and underflowed without showing errors. 

This led to unexpected behavior of the code and was solved by importing the SafeMath library. The library throws an error and reverts the transaction. For Solidity contracts written in versions spanning before and after the change, it is recommended to still implement SafeMath.

What is overflow and underflow?

An underflow happens when we have an unsigned integer and subtract a larger number from it. An overflow happens when an integer gets larger than the maximum value within an arithmetic operation.

How to check for underflow?

The easiest way to simulate an underflow is to assign the value 0 to a variable and decrement it by one. function checkUnderflow() public pure returns (uint) { uint n = 0; n--; return n; }

How to check for overflow?

In the same way, we can simulate an overflow by incrementing the maximum value by one or more. function checkOverflow() public pure returns (uint) { uint n = type(uint).max; n++; return n; }

Why is SafeMath used in Solidity?

In Solidity 0.8 and above the check for underflow and overflow is implemented on the Virtual Machine. If we run the code above the transaction is reverted and a note is returned. call to SafeMath.testUnderflow errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information. If the same code runs on a version below solidity 0.8 the overflow and underflow pass without any error. So we have to use the SafeMath library in any version below Solidity 0.8 to prevent these unexpected and unwanted results. testUnderflow returns: 115792089237316195423570985008687907853269984665640564039457584007913129639935 testOverflow returns: 0

How to import SafeMath

For contracts before Solidity 0.8 it the SafeMath library prevents overflow- and underflows. The library is copied into the source code or imported from open zeppelin: // SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/math/SafeMath.sol"; contract TestSafeMath{ using SafeMath for uint; function simulateUnderflow() public pure returns (uint) { uint n = SafeMath.sub(0,1); return n; } function simulateOverflow() public pure returns (uint) { uint intmax = type(uint).max; uint n = SafeMath.add(intmax, 1); return n; } } The SafeMath library is implemented in three steps:
  1. import the library: import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/math/SafeMath.sol";
  2. activate SafeMath for integers: using SafeMath for uint;
  3. use SafeMath.add(), SafeMath.sub() or similar
After implementing the SafeMath library the result is as expected. The library raises an error and the transaction is reverted. call to TestSafeMath.testUnderflow errored: VM error: revert. revert The transaction has been reverted to the initial state. Reason provided by the contract: "SafeMath: subtraction overflow". Debug the transaction to get more information. If we implement the SafeMath library it is important to consider the correct Solidity version for it. The OpenZeppelin release v3.4 is written for Solidity 0.6 and 0.7. pragma solidity >=0.6.0 <0.8.0; Learn more about versions in Solidity.

        

Summary

Click to jump to section