Additional Solidity Concepts - Discussion

Hey @filip

So, i figured out that it was a memory issue, and the updateBalance needed to be changed (only from you stating that we needed to look at the datalocation).

I still don’t think it works properly as the balance is just updated, not added to my previous inputted balance, unless that wasn’t the point ?

Thanks,
Jonathon

pragma solidity 0.7.5;
contract MemoryAndStorage {
    mapping(uint => User) users;
    struct User{
        uint id;
        uint balance;
    }
    function addUser(uint id, uint balance) public {
        users[id] = User(id, balance);
    }
    function updateBalance(uint id, uint balance) public {
         User storage user = users[id];
         user.balance = balance;
    }
    function getBalance(uint id) view public returns (uint) {
        return users[id].balance;
    }
}
1 Like

Hello,
I’m a little confused about temporary storage when defining variables within a function. Are all variables defined within a function stored in memory? If you create a string variable within a function is it automatically stored in memory??

Thanks,
Brian Y

1 Like

Hey @Brian_Y, hope you are ok.

All functions that have internal variables that will do something on their logic, are stored on the bytecode of the EVM (blockchain), but do not confuse the term “memory” with the memory syntax of solidity.

these are the data location used on solidity:

  • memory: whose lifetime is limited to an external function call
  • storage: the location where the state variables are stored, where the lifetime is limited to the lifetime of a contract
  • calldata: special data location that contains the function arguments.

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.

can u break it down on how u determine if it memory or storage u will input
how do u tell it memory or storage i didn’t really get the video

1 Like

do storage only work for uint

1 Like

pretty simple, when you need to save some data in the blockchain, you use storage. (permanently storage)

Use memory when you need to storage data just for few moments (like creating a variable that only will get data based on blockchain) to then be used to produce a different result.

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.

I must say im proud of myself for this 1. I had absolutely no coding experience before coming to the academy and until now ive always just settled for learning how coding works instead of actually trying to write code of my own. it took me weeks of reviewing notes and studying additional info to start being able to start from nothing and see the code in my mind. It was a lot of work for 1 line of code and after finally getting it right I see how simple the answer was but going back and taking the time to solve the problem on my own was worth it.

pragma solidity 0.7.5;
contract MemoryAndStorage {

mapping(uint => User) users;

struct User{
    uint id;
    uint balance;
}

function addUser(uint id, uint balance) public {
    users[id] = User(id, balance);
}

function updateBalance(uint id, uint balance) public {
     User memory _user = users[id];
     _user.balance = balance;
     users[id].balance=_user.balance;
}

function getBalance(uint id) view public returns (uint) {
    return users[id].balance;
}

}

1 Like

Happy to read it!
I can tell you that your mentality is right, and it is the best mentality to learn how to code.
Take time to think hard, and take time to really understand WHY you do something instead of just copying is what will make you a good developer.
And what you learn this way will remain stuck in your head.

Good job with your code!

I will see you soon in Solidity 201 :slight_smile:

Cheers,
Dani

1 Like

Hey @W1LL

We have an incredibly good Smart Contract Security Course. It is my favourite course of this Academy and you should check it out.
Filip and Ivan go one by one all the hacks happened to Ether and you will code them and their solution yourself.
Check if out!

Cheers,
Dani

1 Like

Not sure if I did this assignment on the old course but here’s my solution:

    function updateBalance(uint id, uint balance) public {
         User memory user = users[id];
         user.balance = balance;
         
         users[id].balance = user.balance;
    }
1 Like

@filip

Never mind, I got it!..sorry!

1 Like
    function updateBalance(uint id, uint balance) public {
        // - This creates a new user to the temporary memory and the user with given ID is assigned to it.
        // User memory user = users[id];
        // - Then the balanced is updated for the user that is saved in temporary memory. And the original users balance
        // will not be updated in persistent storage in map of users.
        // user.balance = balance;
        
        // The balance should be updated to the map
        users[id].balance = balance;
    }
1 Like

Filip, I don’t know if your still answering questions, but i was wondering what questions do you ask yourself in order to find answers on google. I was trying to find the answer to the updateBalance, but i was so unsuccessful in doing so. Btw i love your lessons!!!
Thanks

2 Likes

Hey @jahh, hope you are great.

When you want to research something on google, i could suggest you to use most of the accurate words about your subject.

its quite hard to get a specific topic on updateBalance, so you can be more detailed like: ethereum solidity updating mappings for example. That way google will use those words to seach the most accurate topics about those words.

Carlos Z

2 Likes

Changed line 16 from

User memory user = users[id];

to

User storage user = users[id];

full code below.

pragma solidity 0.7.5;
contract MemoryAndStorage {

    mapping(uint => User) users;

    struct User{
        uint id;
        uint balance;
    }

    function addUser(uint id, uint balance) public {
        users[id] = User(id, balance);
    }

    function updateBalance(uint id, uint balance) public {
         User storage user = users[id];
         user.balance = balance;
    }

    function getBalance(uint id) view public returns (uint) {
        return users[id].balance;
    }

}

bingo bango the code works as intended we all go home early.
Now the question becomes do you want to be storing that data in storage as it would be pricier computation wise than keeping it in memory right? Which I suppose comes down to weather or not we need to use the updated balance elsewhere. I argue, we probably do.

2 Likes

Nice solution @IntrepidShape :ok_hand:
… 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 :+1:

1 Like

Hey Mr. Z , wanted to thank you for this reply, it gives me a clear picture on how to search

1 Like

Does anyone know why would this part of code inside the contract

`uint x;
    constructor(uint _x) { 
        x = _x; 
        
    }`

Give an error in remix:
creation of multiSigWallet_test errored: Error encoding arguments: Error: invalid BigNumber string (argument=“value”, value="", code=INVALID_ARGUMENT, version=bignumber/5.1.1)

I found out why…I haven’t typed in the inputs before deployment in remix.

1 Like

Well done for working it out @vasja :+1:

Yes… if your constructor has parameters, then values need to be input for these when the contract is deployed.

1 Like