Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer using uint256 instead of a type with less than 256 bits #6

Open
cleanunicorn opened this issue Jul 28, 2021 · 0 comments
Open

Comments

@cleanunicorn
Copy link
Member

cleanunicorn commented Jul 28, 2021

Description

The EVM works with 256bit/32byte words. For smaller data types, further operations are performed to downscale from 256 bits to the required lower bites type, and therefore having uint8 as an iterator consumes more gas than keeping it to uint256.

There are several places where uint8 is used as the type for the loop iterator:

https://github.com/monoceros-alpha/review-opyn-perp-vault-templates-2021-07/blob/3d44603300dd9abffe5a1c1e1c2647e9f6b80c7b/code/contracts/core/OpynPerpVault.sol#L420

https://github.com/monoceros-alpha/review-opyn-perp-vault-templates-2021-07/blob/3d44603300dd9abffe5a1c1e1c2647e9f6b80c7b/code/contracts/core/OpynPerpVault.sol#L441

Recommendation

The example below shows the difference between 2 variants of code, one using uint8 and the other uint256 for the iterators:

pragma solidity ^0.7.2;

/**
 * Show the difference in gas costs between a loop that uses a uint8 variable
 * and one that uses uint256 variable.
 * 
 * Both contracts compiled with `Enable Optimization` set to 200 runs.
 */

contract LoopUint8 {
    // 1st call; size == 0: gas cost 21479
    // 2nd call; size == 1: gas cost 21558
    // 3rd call; size == 5: gas cost 21826
    // 4th call; size == 10: gas cost 22161
    function add(uint8 _size) public returns(uint8) {
        uint8 sum = 0;
        
        for (uint8 i = 0; i < _size; i++) {
          sum += i;
        }
        
        return sum;
    }
}


contract LoopUint256 {
    // 1st call; size == 0: gas cost 21452
    // 2nd call; size == 1: gas cost 21519
    // 3rd call; size == 5: gas cost 21739
    // 4th call; size == 10: gas cost 22014
    function add(uint256 _size) public returns(uint256) {
        uint256 sum = 0;
        
        for (uint256 i = 0; i < _size; i++) {
          sum += i;
        }
        
        return sum;
    }
}

It's important to note that the loop below will always fail because of an out of gas issue. The iterator never hits the limit to stop, it will max out at 255 and restart from 0, thus it will never be larger than 300 to trigger the end of the loop.

for (uint8 i = 0; i < 300; i++) {
    // do something
}

Recommendation

Use uint256 for the loop iterators.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants