DEV Community

Rushank Savant
Rushank Savant

Posted on • Updated on

Avoiding storage access in functions - 2

This post is in continuation from the last one which was on saving gas by referencing data from memory. Now we will see a case where this can be contradictory.

Consider the following contracts:

contract varReferencing_1{
    uint[] public arr;
    uint public arrLength;

    function addItem(uint _item) external {
        arrLength = arrLength + 1; // updating state

        arr.push(_item); // adding element

        for (uint i; i < arrLength; i++) {
            arr[i] = arrLength + i; // updating state
        }
    }
}


contract varReferencing_2{
    uint[] public arr;
    uint public arrLength;

    function addItem(uint _item) external {
        uint _arrLength = arrLength + 1; // storing into memory

        arr.push(_item); // adding element
        uint[] memory _arr = arr; // storing into memory

        for (uint i; i < _arrLength; i++) {
            _arr[i] = _arrLength + i;
        }

        arr = _arr; // updating state
        arrLength = _arrLength; // updating state
    }
}


contract varReferencing_3{
    uint[] public arr;
    uint public arrLength;

    function addItem(uint _item) external {
        uint _arrLength = arrLength + 1; // storing into memory

        arr.push(_item); // adding element

        for (uint i; i < _arrLength; i++) {
            arr[i] = _arrLength + i;
        }

        arrLength = _arrLength; // updating state
    }
}
Enter fullscreen mode Exit fullscreen mode

All the three contracts have the exact same functionality, to push new element to the array and sum the index of all the elements with new array length and update it in array. (Note: this functions have no use in practical, these are just examples)

Lets see the differences and the gas spent for each contract:

varReferencing_1
addItem increases the state variable arrLength by 1, pushes new element _item to state variable array arr and updates each array element with new length + index.

Image description

varReferencing_2
addItem increases the copy of state variable _arrLength by 1, pushes new element _item to state variable array arr and makes it's copy in memory. Then these copies are used to perform further operations and then assigned to original state variables.

Image description

varReferencing_3
addItem makes copy of arrLength state variable in memory, but not of the arr. And rest of the operations are same.

Image description

Conclusion

varReferencing_2 was expected to be most gas efficient because it makes copies of both state variables, but it turned out to be most expensive. This was probably due to copying arr from storage to memory and then back to storage after all the operations.
In varReferencing_3, we just made copy or arrLength and that turned out to be the most gas efficient method.

Top comments (0)