3

Say I have a transaction which will execute a function on a smart contract. This function will access storage, its own and that of other contracts, potentially multiple times. For example it may look up the ERC20 token balances for a set of addresses, etc.

By adding all accessed address - storage keys pairs to the access list of the tx before hand, I should be able to save on gas as 'warm storage' is cheaper to access.

How do I systematically build the access list for a tx?

2 Answers 2

3
+50

Geth (starting from version 1.10.2) includes a new eth_createAccessList RPC method that you can use to generate access lists. It is used like eth_estimateGas, but instead of a gas estimation, it returns something like this:

{
  "accessList": [
    {
      "address": "0xb0ee076d7779a6ce152283f009f4c32b5f88756c",
      "storageKeys": [
        "0x0000000000000000000000000000000000000000000000000000000000000000",
        "0x0000000000000000000000000000000000000000000000000000000000000001"
      ]
    }
  ],
  "gasUsed": "0x8496"
}

Source: https://hackmd.io/@fvictorio/gas-costs-after-berlin#The-eth_createAccessList-RPC-method

3
  • How common is the usage of access list? The benefits seem very clear to me blog.infura.io/post/…, but i could not find many examples in practices May 30, 2023 at 15:42
  • I know MEV bots use it, but in my experience only them, never a dapp.
    – 0xSanson
    May 30, 2023 at 22:01
  • Oh interesting. The authors of EIP-2930 argue that today Access lists are difficult to construct in real-time and hence there is only a 10% discount. But this might change in the future. Source: Security Considerations in eips.ethereum.org/EIPS/eip-2930?ref=infura.ghost.io May 31, 2023 at 8:10
2

How to find storage slot

1. Using foundry

Foundry's forge & cast functions have a built-in way to get a layout of storage slots.

If working in a foundry project:

forge inspect <CONTRACT_NAME> storage

or, a deployed contract:

cast storage <ADDRESS> [SLOT]

2. Count yourself

You could also count the storage slots manually. You'd have to walk through the versions storage slot layout

More information

However... diving into this, I'm actually not sure how to make viewing storage more gas efficient in assembly/yul than just regular solidity.

// SPDX-License-Identifier: MIT

pragma solidity 0.8.18;

contract GetWarmStorage {
    // 2,327 gas (gas to compare)
    uint256 public myNumberOne;

    uint256 private constant SLOT = 0;

    constructor() {
        myNumberOne = 123;
    }

    // 2,247 gas (-80 gas)
    function readStorageNormal() external view returns(uint256) {
        return myNumberOne;
    }

    // 2,332 gas (+5 gas)
    function readStorageAssembly() external view returns (uint256) {
        assembly {
            let result := sload(myNumberOne.slot)
            mstore(0, result)
            return(0, 0x20)
        }
    }

    // 2,291 gas (-36 gas)
    function readStorageAssemblyTwo() external view returns (uint256 result) {
        assembly {
            result := sload(myNumberOne.slot)
        }
    }

    // 2,310 gas (-17 gas)
    function readStorageAssemblyKnowingSlot() external view returns (uint256) {
        assembly {
            let result := sload(SLOT)
            mstore(0, result)
            return(0, 0x20)
        }
    }

    // 2,269 gas (-58 gas)
    function readStorageAssemblyKnowingSlotTwo() external view returns (uint256 result) {
        assembly {
            result := sload(SLOT)
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.