Data Location Assignment

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 {
        users[id].balance = balance;
    }

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

}
1 Like

Switch keyword memory to storage. So the problem was that memory was only saving user balance while the function ran ,so anything happening after was not getting saved. Replacing memory with storage allows the user balance data to persist over time and function executions.

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

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
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]; // replace memory to storage
         user.balance = balance;
    }

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

}
1 Like
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

Nice solution @Renz :ok_hand:

… and it’s good to see you back here in the forum! I hope you’re enjoying the course :slightly_smiling_face:

On the whole, your explanation is good. Here are some additional comments …

It was a temporary copy of the whole User struct instance (stored in the mapping) which was first stored in memory …

User memory user = users[id];

Then, the new balance was assigned to the balance property of this temporary copy, where it was only saved until the function had finished executing, at which point it was lost …

user.balance = balance;

Yes … and it’s interesting to understand how this actually happens …

When we define the data location of a local variable as storage, this creates a storage pointer. This only points to (references) the value already saved in persistent storage which is assigned to it (in our case users[id] ); it doesn’t create or store a separate copy of this value, as it would if we defined the data location as memory . A storage pointer is like a temporary “bridge” during execution of the function to wherever in the contract state it points to (in our case a specific User struct instance in the mapping).

Any value which is then assigned to a property of the local “pointer” ( user ) will effectively update that same property of the specific User instance in the mapping which is referenced by the pointer. This enables a specific user’s balance (stored persistently in the mapping) to be reassigned with the new balance (input into the function), before our “bridge” disappears when the function finishes executing…

user.balance = balance;

Just let me know if you have any questions.

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 {

         users[id] = User(id,_balance);

    }

    function getBalance(uint id) view public returns (uint) {

        return users[id].balance;

    }

}
1 Like
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.7;
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 {
         users[id].balance = balance;
    }

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

}

1 Like

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 {

     users[id].balance = balance;

}

function getBalance(uint id) view public returns (uint) {

    return users[id].balance;

}

}

1 Like
pragma solidity 0.8.7;
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 {
        users[id] = User(id, balance);
    }

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

}
1 Like

Hi @thanasornsawan,

Your solution has, effectively, made the updateBalance function exactly the same as the addUser function.

While this does still work…

I assume you’ve already seen the 2 alternative solutions suggested in the follow-up video. Can you see how they are more suitable?

You may also find this related discussion interesting, which starts in the post I’ve linked to and continues over several more.

Just let me know if you have any questions :slight_smile:

1 Like

Nice solution @firequo :ok_hand:

… and it’s good to see you back here in the forum! I hope you’re enjoying the course :slight_smile:

Hi @Tomaage ,

Your solution has made the updateBalance function exactly the same as the addUser function…

While this does still work…

I assume you’ve already seen the 2 alternative solutions suggested in the follow-up video. Can you see how they are more suitable?

You may also find this related discussion interesting, which starts in the post I’ve linked to and continues over several more.

Just let me know if you have any questions :slight_smile:

1 Like

Thanks Jon . I posted before I saw the solution because if it was something flawed I did not see, its good to have this forum point it out to me so I learn from it.

When I did enginering school, we had a hydrolics enigneer who would always make us install our test equipment the worng way, or les optimal wasy, so we we could see the mistake when we turned it on and everything was shaking and making strange noises, and then understand better why the correct way was more optimal.

1 Like

Yes… posting your own solution, and then seeing if the feedback you get matches what you realised yourself when you checked the solution code, and having a good think through any additional points that are raised … is a great way to learn :+1:

@jon_m thank you for help describe concept.My logic not well much.
Yes,I already see the 2 alternative solutions suggested in the follow-up video.It use just property inside users.Not replace value as I do.

        //solution 1

        users[id].balance = balance;

         //solution 2

         User storage user = users[id];

         user.balance = _balance;
1 Like

Hi @thanasornsawan,

Both your solution and the ones shown in the follow-up video replace values. The difference is that…

  • Your solution replaced the whole User struct instance (the value mapped to an address key in the users mapping). This isn’t wrong, but as you’ve understood, it’s unnecessary.

  • The two alternative solutions shown in the follow-up video replace just the uint value stored in the struct instance’s balance property.

I’m sure this is what you’ve understood, but I just wanted to clarify the correct terminology.

I hope that’s helpful :slight_smile:

no idea but I gave it my best shot and it seems to be working to me… lol Moving on to see others and the solution in next video :slight_smile:

1 Like

Nice solution @casadcode :ok_hand:

Just make sure that you use the more recent Solidity version 0.7.5 (as used in the course videos). It doesn’t make any difference for this assignment, but it will for the rest of the course.

Also, for your next assignments, please don’t post screen shots, because we can’t copy and paste your code in order to execute and test it, if we need to. Instead, follow the instructions in this FAQ: How to post code in the forum

Let me know if you have any questions :slight_smile:

1 Like
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 {
        users[id].balance = balance;
    }

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

}
1 Like