Search code examples
ethereumsolidity

How does assigning to `uint` save "storage read" costs in Ethereum?


I'm taking a look at the uniswapv2 tutorial walkthrough.

The followng is in reference to this function in the github repo and the tutorial states the following:

    uint _kLast = kLast; // gas savings

The kLast state variable is located in storage, so it will have a value between different calls to the contract. Access to storage is a lot more expensive than access to the volatile memory that is released when the function call to the contract ends, so we use an internal variable to save on gas.

So in traditional programming, _kLast would be a reference to kLast. _kLast is referenced 3 more times after it's instantiation.

  • Had they used just kLast as the variable, and not assigned it to uint, would it cost a storage read each time kLast is used?
  • If this is NOT the case, then I really don't understand how they're saving on gas, can someone explain?

Solution

  • Each storage read (opcode sload) of the same slot costs 2,100 gas the first time during a transaction, and then 100 gas each other time during the same transaction. (After the EIP-2929 implemented in the Berlin hardfork. Before that, it was 800 for each read no matter how many times you performed the reads.)

    Each memory write (opcode mstore) and each memory read (opcode mload) cost 3 gas.


    So in traditional programming, _kLast would be a reference to kLast

    In this particular Solidity snippet, _kLast is not a reference pointing to the storage. It's a memory variable that has value assigned from the storage variable.

    So 3 storage reads - not creating the memory variable - would cost 2,300 gas (= 2,100 + 100 + 100).

    But because the code creates the memory variable, it performs one storage read (2,100 gas), one memory write (3 gas), and three memory reads (3 x 3 gas) - totalling 2,112 gas. Which is a cheaper option.


    Some other EVM-compatible networks, such as BSC, might still use the original gas calculation of 800 per each sload. Which would make even larger difference - non-optimized 2,400 gas (3 x 800), and optimized 812 gas (800 + 3 + 3x3).