1

I have a mapping linking an email (bytes32) to an Id (uint256) named emailToId:

    mapping(bytes32 => uint256) public emailToId;

I also have functions in my smart contract that use this mapping, but I don't know what is better:

1 - use the mapping every time I need it

    function changeUserNameAndEmail (
        bytes32 email,
        bytes32 newName,
        bytes32 newEmail
    ) public {
        users[emailToId[email]].name = newName;
        emailToId[newEmail] = emailToId[email];
        delete emailToId[email];
    }

2 - store the mapping result in a variable userId and re-use the variable every time I need it

   function changeUserNameAndEmail (
       bytes32 email,
       bytes32 newName,
       bytes32 newEmail
   ) public {
       uint256 userId = emailToId[email];
       users[userId].name = newName;
       emailToId[newEmail] = userId;
       delete emailToId[email];
   }

PS: this is a simple example, but there are some functions that I need to use the emailToId[email] several times... should I use the mapping or store it in a variable in terms of gas cost and performance?

2 Answers 2

0

This is a bit tricky.

The exercise that you did comparing the gas that each approach consumes is the way to go.

Usually, there's no need to make a copy of a mapping value in memory. Reading and writing directly to it might be enough.

But sometimes, it may be useful to make a copy of the value in memory if we know that we will read/write to a mapping multiple times, and maybe we just need to copy the value, do many operations on it and then write it just once to the mapping. Especially if we are using a loop.

Keep in mind that making a copy of a value in memory also costs gas, starting from 3 gas units. The total cost of the copy will depend on the size of the data you are copying. So, sometimes we may not get any benefit from making a copy of the data in memory.

If you take a look at the opcodes and the gas they consume here, you will notice that MSTORE (storing a value in memory) uses 3* gas to store data in memory. The * means that it will depend on the size of the data being copied. MLOAD (reading a value from memory) consumes the same 3*.

Notice that SLOAD uses 800 gas to read a word (32 bytes) from storage. Also notice that SSTORE uses 20000* to store values in storage, depending on the values to be saved, starting at 20000 units of gas.

Conclusion:

If you need to inevitably read from a mapping or storage x times and you have to inevitably write to a mapping x more times, then think if you really need make a copy in memory on top of that, which you probably won't.

Don't make a copy of the data in memory unless you need to and see that is beneficial. Because if making the copy in memory is unnecessary, then you would be wasting resources because you would be reading/writing from and to storage and on top of that making an extra copy of the data in memory. Sometimes it will be useful, sometimes it won't.

Compare both approaches and you can select the one that uses less gas. When using loops, check if you are modifying the same state variable multiple times and decide if you should better create a copy in memory, modify the copy and then update the storage just once with the result.

Check all the EVM opcodes and the gas they consume here: https://github.com/crytic/evm-opcodes

0

I used Remix IDE to test both solutions and the result was:

1 - store the mapping result in a variable userId and re-use the variable every time I need it

gas: 35471 gas

transaction cost: 30844 gas

2 - use the mapping every time I need it:

gas: 39199 gas

transaction cost: 34086 gas

So I'll choose to store the mapping result in a variable userId and re-use the variable every time I need it. Note that I'm not writing values to the mapping, just accessing and reading it. For this specific case and other test cases that I did, it was better, but I suggest you compare the gas cost for your functions as well.

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.