code-423n4 / 2021-12-sublime-findings

0 stars 0 forks source link

Gas: Upgrading solc version and removing SafeMath #39

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Handle

0xngndev

Vulnerability details

Impact

Reduce code size and gas expenditure by upgrading the compiler version to version 0.8.0 or higher in order to remove SafeMath from your contracts.

I was curious to test how much more expensive both in gas and code size was to use SafeMath contrary to simply using a compiler version higher than 0.8.0. So I wrote a small contract with a function that performed:

And using Dapptools I tested gas usage and code size first using 0.8.10 compiler version without SafeMath, and then using SafeMath.

Results: Without SafeMath:

Using SafeMath:

With these results in mind, I would suggest upgrading your compiler version if possible and stop using SafeMath as it's not necessary with compiler version higher than 0.8.0. You can also make use of unchecked in higher versions to save even more gas if you are certain the arithmetic operation you

Proof of Concept

Here is the example contract I ran to test this:

pragma solidity 0.8.10;

contract SafeMath {
  function add(uint256 x, uint256 y)
    public
    pure
    returns (
      uint256,
      uint256,
      uint256,
      uint256
    )
  {
    uint256 addResult = x + y;
    uint256 mulResult = x * y;
    uint256 divResult = x / y;
    uint256 substractResult = x - y;
    return (addResult, mulResult, divResult, substractResult);
  }
}
pragma solidity ^0.7.6;

import "@openzeppelin/contracts/math/SafeMath.sol";

//inlined saves gas in the calling function

contract SafeMath {
  using SafeMath for uint256;

  function add(uint256 x, uint256 y)
    public
    pure
    returns (
      uint256,
      uint256,
      uint256,
      uint256
    )
  {
    uint256 addResult = x.add(y);
    uint256 mulResult = x.mul(y);
    uint256 divResult = x.div(y);
    uint256 substractResult = x.sub(y);
    return (addResult, mulResult, divResult, substractResult);
  }
}

And here is the test file

//SPDX-License-Identifier: unlicensed
pragma solidity 0.8.10;

import "ds-test/test.sol";
import "../SafeMath.sol";

contract SafeMathTest is DSTest {
  SafeMath safeMathContract;

  function setUp() public {
    safeMathContract = new SafeMath();
  }

  //concrete test
  function testAdd() public logs_gas {
    safeMathContract.add(10, 5);
  }
}

Tools

DappTools

ritik99 commented 2 years ago

We use Uniswap's oracle library which in turn uses a library that is not yet compatible with >=0.8, hence we cannot upgrade at the moment