Data Location Assignment [OLD]

Exactly, each code line on Solidity can have a gas price (opcodes), so developers will try to design the functions with the lowest amount of variables possible, or only exactly what is need it and nothing more.

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

Carlos Z.

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

Changed part:

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

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

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

Just needed to change this line…
function updateBalance(uint id, uint balance) public {
users[id].balance += balance;
}

… and it worked!

EDIT: Except, it wasn’t supposed to ADD to the balance, but just update it. So, it doesn’t need the +=… just the = (not an increment, just an overwrite)

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;
    }
    
    // I could think of this other way too.. 
    // 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

the function updateBalance is using mapping where we update the balance of the user with a provided id. The struct is defined outside the function and uses storage or persistent data storage.

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

Thank you for your post. It brought clarity to the 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 {
   //  User memory user = users[id];
     users[id].balance = balance;
}

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

}

1 Like
pragma solidity 0.5.12;
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

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

This works :slight_smile:

1 Like

Hello,
My question is not about storage vs memory, but it’s about this pattern of attaching logic to the functions below in Solidity, I hope you can help explain what is going on in each function in different words.
Why can’t we just return user.balance in the last function below?
Is the flow of id and balance starting with Struct User, then the mapping of “users” to User, then users[id], then users[id] to User user, then user.balance, then finally users[id].balance?
I’m really confused as to how mapping works and why we can’t just return user.balance.
Also what is the difference between User, user and users?
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 balance) {
    return users[id].balance;
}

}

Hey @Tesh

Why can’t we just return user.balance in the last function below?

Let’s clarify the way mappings work.
mapping ( key => value ) mapping_name.

In order to access data in a mapping you always have to provide a key.
In order to access a mapping:

mapping_name[key];

In this case you have a mapping that points to a struct, let’s simplify:


pragma solidity 0.7.5;

contract TestContract {
    
    struct Test{
        uint num;
    }
    
    mapping(uint => Test) public tests;
}

Let’s now translate mapping(uint => Test) public tests;, you can read it as follow:

There is a mapping that asks for a key of type uint and returns a struct called Test.

Based on the sentence above, we can create a setter function:

function set(uint _id) public {
        tests[_id].num = 10;
    }

Our setter function asks for an _id of type uint (that will be our mapping key).
We then set num for key: _id to 10.

Now the getter function, remember that we always need a key to access our mapping!

    function get(uint _id) public view returns (uint) {
        return tests[_id].num;
    }

Our getter function asks for an _id of type uint (that will be our mapping key).
We then return the number that is stored in tests[key].num.


I have used the example above as I think it will be more clear for you in order to understand mappings.

You can access mappings also by using Filip example (this will be mandatory in other cases).
Keep considering our contract above, let’s change the setter function:

function set(uint _id) public {
         Test storage testsPointer = tests[_id];
         testsPointer.num = 10;
    }

This does exactly the same thing as the previous setter, is just wrote differently.
You can read it as:
Test storage testsPointer = tests[_id]; -> There is a struct called Test that can be access with a mapping that uses tests[_id].
To make it short and write as less code as possibile, I will save tests[_id] in something called testsPointer.

So you can read testsPointer == tests[_id]

Now it’s easy for you to understand because is exactly the same thing as in our previous setter:

testsPointer.num = 10;

Which is the same as tests[_id].num = 10 :slight_smile:

Hope it’s clear!

Cheers,
Dani

1 Like

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

}

Hi @filip,

I’m confused, it seems like your GitHub code which we are supposed to copy and modify is the solution. I understand my “solution” was not what was asked for :grimacing:

1 Like

Hi @Karla

Your solution is not what Filip was asking for but is still correct :slight_smile:
Filip is asking to overwrite the user balance while you are increasing it instead (makes a lot of sense anyway so I cannot say that it’s wrong).
Just for the sake of the exercise, write an updateBalance that overwrite the previous balance with the new one.

If the previous balance is 5 and the new balance is 10, your function update should set the balance to 10 not 15.

Cheers,
Dani

1 Like

This is a great explanation, thank you for taking the time.

1 Like

Hi @dan-i,

Thank you for checking! I realised I clicked the link on to the Data Location assignment solution video, that’s why the code was obviously the solution :roll_eyes:
However I have redone the 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 {
    User storage user = users[id];
         users[id].balance = balance;
    }

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

}

The first statement in the updateBalance function assigns users[id] ,which is declared globally, to a variable stored in memory. Therefore I replaced memory with storage. We could also get rid of the first statement completely, because there is no need to assign users[id] to a variable.

1 Like

I wasn’t able to update the balance, even with your solution, it didn’t work. I don’t know why.