Data Location Assignment

Hi @patgeek,

If you had only included this line of code in your updateBalance() function body, then your contract would have compiled and solved the task.

Your idea of including an assert statement to check the new balance is perfectly OK, but the condition needs an equality comparison operator (==) instead of an assignment operator (=). If you make this modification, your contract will now compile and work as you intend.


Even though the initial idea of this assignment is to update the existing balance by replacing it with the new one, I actually think that it does make more sense to do what you’ve done, 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 a new balance.

There is always more than one solution to these assignments, and alternative interpretations are equally valid.

Let us know if anything is unclear, or if you have any questions :slight_smile:

// SPDX-License-Identifier: GPL-3.0

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

Hey guys! This is my solution!

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
// 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 getBalance(uint id) view public returns (uint) {
        return users[id].balance;
    }

}

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

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

I think I did the bare minimum requirement. Not sure I understand why yet, but I guess it works as the assignment intended. Time to peek at the answer from Filip hehe.

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

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

}
2 Likes

Hey guys, here is the solution I found to be simpler. Cheers

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

}
2 Likes

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;

}

}

2 Likes

hi, although copy-pasting the problem & substituting memory with storage would have done the trick, I preferred to practice some of the past topics, and re-wrote the contract to include a constructor, modifier and some require checks.

updateBalance has the possibly unintended side-effect of creating a new user, in case we pass the id of a non-existing user. Perhaps adding a require check of the user balance having a balance > 0 would be a possible way to prevent this.

pragma solidity 0.8.13;
contract MemoryAndStorage {
    address owner;

    mapping(uint => User) users;

    struct User {
        uint id;
        uint balance;
    }

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

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

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

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

i added the require in order to do not let overwrite an existing user

    function addUser(uint id, uint balance) public onlyOwner {
        require(users[id].balance == 0, "The user already exists"); // validate not to replace an existing user
        users[id] = User(id, balance);
    }

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

Mappings that involve structs are always of “storage” type. So are state variables. The problem with the code is that it instantiates a new variable “User” in memory, assigning it the value of the user in storage. But “memory” type variables are lost after the execution of the function.

What needs to be done is to change “User memory user” to “User storage user” so that its value is stored. Or even better (and probably cheaper?) to directly assign the value to the state variable, without creating a new User variable instead, using

function updateBalance(uint id, uint balance) public {
         users[id].balance = balance;
    }
3 Likes
pragma solidity 0.8.13;

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

}
2 Likes

The task at hand was to enable the update of the balance of the user.
The updateBalance function was creating a copy of the user struct in memory from the mapping.
This meant that after the execution of the function the struct would get removed.

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

The solution is to directly modify the mapping on the right key.
This means that the contract state variable is saved and available between executions of the functions.

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

so after overthinking it and trying about multiple different syntax. I used google to figure this one out and feel like a total fraud but this is the solution I used. constructive criticism welcomed

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

}
2 Likes
My Solution
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;
    }

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

}```
2 Likes