Nice solution @IntrepidShape
… and welcome to the forum! It’s good to see you here, and I hope you’re enjoying the course!
Good question!
In actual fact, changing memory
to storage
here, reduces the gas consumed when executing this function. I know, at first, this sounds counter-intuitive, but it is because…
User memory user = users[id];
… using memory
, here, creates a local copy of the user’s data stored in the mapping (users[id]
). Whereas using storage
, doesn’t create a separate copy of this data in persistent storage, but instead creates a pointer (a reference) to a specific User
instance that already exists in the users
mapping — the one which has, as its key, the id
parameter input into the function. This means that when balance
is assigned to user.balance
in the second line, it is effectively being assigned to users[id]
in the mapping.
user.balance = balance;
The key to understanding why using storage
is cheaper than memory
here is the fact that, with storage
we do not need to create a local copy of our data before updating it. As you say…
… we do need to keep a record of each user’s current balance, and so whether we use memory
or storage
, we still have to update the mapping whenever the balance changes.
The following solution to the same problem, using memory
, has a much higher gas consumption than your solution, because it involves making a local copy of our data before assigning it to the mapping, instead of assigning it directly via the “pointer”.
function updateBalance(uint id, uint balance) public {
User memory user;
user.balance = balance;
users[id] = user;
}
I hope that explanation makes sense. However, let us know if anything is unclear, or if you have any questions. It’s great that you are thinking about what effects the code we use may have on important issues such as gas cost