Data Location Assignment [OLD]

This is how it worked for me:

image

First, in updateBalance I changed User memory user to User storage user.
It still didn’t work. I noticed that in header of getBalance it says view public, but in lecture examples it was public view. I flipped those and it worked, but I’m not sure why. They are separate keywords each with its own use.

1 Like

This is my solution.
pragma solidity 0.5.1;
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

two ways to do the problem…here is the final one i used.

pragma solidity 0.5.1;
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

Hi @hannezzon,

Your solutions are correct, and it’s great that you are attempting to explain how the code works.

Just to clarify…
The locally created user variable doesn’t reference the User struct. It creates a new instance of the User struct. The User struct is like a blueprint which is used to declare new instances with the same data structure.
As this new instance is marked storage (instead of memory), it creates a direct reference to the instance with the same id key, stored permanently in the users mapping. Therefore, when the new balance is assigned to the user instance, it is also assigned permanently to the instance with the same id stored in the users mapping.

1 Like

Hi @MarcisB,

That should be the only change needed.

It should work with either view public or public view , so it’s strange that yours didn’t work at first. Either order compiles successfully for me in Remix.

By the way, please add your code by formatting it within the post itself, instead of posting a screen shot. That way it can be copied and pasted into a text editor and executed, which also makes reviewing and debugging easier. To format your code, click on the </> icon in the menu at the top of this forum’s text editor. This will give you 2 sets of 3 back ticks.
```
input your code here
```
If you now input your code between these, you will end up with it nicely formatted. You should always format the code you post, as it is then much clearer and easier to read, and easier for someone else to copy and paste into a text editor for review and execution. It also makes it easier for you to organise your code with the correct spacing and indentation etc. and to spot any errors or copy-and-paste slips

1 Like

Hi @Robert_Jones,

Your solution is correct :ok_hand:

Actually, there are a lot more than just 2 alternative solutions. If you have a browse through this discussion topic, you’ll see several more.

1 Like

pragma solidity 0.5.1;
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

Hi @padlanau,

Your solution is correct :ok_hand:

By the way, please add your code by formatting it within the post itself, instead of posting a screen shot. That way it can be copied and pasted into a text editor and executed, which also makes reviewing and debugging easier. To format your code, click on the </> icon in the menu at the top of this forum’s text editor. This will give you 2 sets of 3 back ticks.
```
input your code here
```
If you now input your code between these, you will end up with it nicely formatted :slight_smile:

1 Like

pragma solidity 0.5.1;
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;
}

}

Essentially change the memory to storage in the updateBalance function.

1 Like

Thanks Mate. The reason why I did the screenshot was to show that I tested it in Remix.
Cheers…

1 Like

User storage user = users[id];

Hi @look_y,

This line on its own in the function body won’t work, as you haven’t assigned the new balance to the user instance stored in the mapping. Can you at least post the complete updateBalance function, so we can see your solution in context? :slight_smile:

1 Like

Change line 16 in the contract to : User storage user = users[id];
changing storage type to storage will create a pointer to storage. any change in user object will be reflected in the storage itself. if we use memory type it creates a new copy of data. If any update is done on copied data, it will not reflect in the original copy.

1 Like

I change Data Location type in function updateBalance

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

Hi @mansoor,

That’s correct.

Just to clarify, it’s the data location that we are changing to storage. and this creates a “pointer” (as you say) to the users mapping, and so any change to the user instance will also be reflected in the mapping (and so the change is stored permanently).

I think this is what you were trying to express. Hopefully, that’s made the terminology clearer for you :slight_smile:

That’s essentially correct… in this case, the user instance is only held temporarily within the local scope of the function, and so when the function has finished executing it will be lost along with any modifications made to it during execution. This means that the modifications aren’t reflected in the mapping.

2 Likes

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

1 Like

@look_y Perfect! :slight_smile:

thank you for telling me

1 Like

Hi, posting my solution, I resaved the to the mapping and seems to do the job

pragma solidity 0.5.1;
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] = user;
    }

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

}
1 Like