Data Location Assignment

Hi @nbkeaton,

Good to see you back here in forum after a while :slight_smile:

Your notes are good, and changing the local user variable’s data location from memory to storage is essentially correct :ok_hand: but your code doesn’t compile, and so your contract can’t be deployed. You should have got two compiler errors, which also highlight the lines where these errors occur with red indicators. If you hover over these red indicators you will see the error messages. These error messages explain where the specific errors are in your code. You will also find these error messages at the bottom of the Solidity Compiler panel.

You will see that your error is easily fixed. And this also highlights the importance of not mixing up the names of state variables (or mappings) and local variables, especially if they are similar.

Let me know if you have any questions about how to correct this.

Hi!

My solution for the Data Location Assignment is:

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

Cheers!

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.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 += 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 memory user = users[id];

         // user.balance = balance;

         users[id].balance = balance;

    }

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

        return users[id].balance;

    }

}
1 Like

Hi, I apologize for posting not relevant to the task :); I calculated the total balance corresponding with a certain id.

1 Like

Hi @DNC,

Both of your solutions are equally valid and relevant to the task :ok_hand:

Even though you probably realised that the initial idea of this assignment is to update the existing balance by replacing it with the new one (your second solution), I actually think that it does make more sense to do what you’ve done in your first solution, and add an amount to the user’s existing balance using the addition assignment operator+= (instead of the assignment operator= ).

However, if we add to, instead of replacing, the existing balance, I think the code looks clearer and more readable if we also change the name of the balance parameter to amount, because we are adding an amount to the balance (to give a new total balance), rather than replacing it with the new total balance.

There is always more than one solution to these assignments, and alternative interpretations are equally valid. You can always add comments to your code to explain anything you’ve done a bit differently or are unsure about :slight_smile:

Let me know if you have any questions.

Thank you for all the clear, on point, supportive feedback Jon.
I sincerely appreciate it and actually think I needed it :).
May you have a great weekend!

1 Like

Modified the updateBalance function to simply update the correct balance, original code is using a different variable.

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

Nice solution @DanDD :ok_hand:

… and good to see you back here in the forum :slight_smile:

Just to add some further detail to your explanation …

… in persistent storage in the mapping.

The original code assigns the new balance to a local variable, which only stores the new balance temporarily in memory. Because the new balance isn’t subsequently assigned to persistent storage, it is lost as soon as the function finishes executing.

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.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.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

Here’s my solution, pretty simple to me.

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

Nice solution @shawnf8992 :ok_hand:

… and good to see you back here in the forum :slight_smile:

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);
    }

    // solution 1: change data location from memory to storage 
    function updateBalance(uint id, uint balance) public {
         User storage user = users[id];
         user.balance = balance;
    }

    // solution 2: access storage directly 
    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

Hi @reiss … and welcome to the forum! I hope you’re enjoying the course so far :slight_smile:

You have nicely demonstrated two alternative solutions for this assignment, and your code is very well presented with excellent formatting. This is a great start :muscle:

1 Like

Your explanation set me in the right direction. Thanks.

1 Like

Hi, this is my solution.
In the updateBalance function, the line of code User memory user = users[_id]; tells Solidity to create a new temporary copy in the memory, so when we change the balance, it is the balance of the copy and gets lost when the next function call gets executed. To fix it, we replace the memory with storage User storage user = users[_id];, so that we can change the balance of the user permanently.

// SPDX-License-Identifier: MIT

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 getUser(uint _id) public view returns(uint) {
        return users[_id].balance;
    }
}
1 Like

I removed the user variable, because this way, when we update the balance, it’s not just the copy of the user that we’re updating. (Alternatively, one could also change “memory” to “storage” in the original function.

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