Data Location Assignment

I only see the problem with function updadeBalance(), which can be solved like that:

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

or

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

works for me.

1 Like

Hi @jon_m,

Thanks for spotting my mistakes! It does make sense to change the assert statement like you say.

Cheers :sweat_smile:

1 Like

1 Like

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

}
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

change the following line of code:

Old Version:
User memory user = users[id];

New Version
User storage user = users[id];

1 Like

from what i can see, in the updateBalance function, we are assigning the Users mapping to a user variable with ‘memory’ data location properties. Therefore, the balance input assigned to this user variable will only be stored temporarily within the function as long as it runs. This function is neither pure or view and hence has the right to change a global state variable. We simply replace memory with storage and the state variable will be modified.

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

}

I changed the updateBalance code to update the storage variable instead of the memory variable in the updateBalance function

1 Like

Here is the 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;
}

}

1 Like

Here is my solution. I rewrote the upDate balance function to take the balance input and update the user’s balance in the array.

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

@Bdos87

Indeed, perfect explanation.

Happy learning :grinning:
Abel

I have directly modified the function updateBalance so that it directly modifies the mapping, without the need of specifying whether to point to a variable in memory or storage

pragma solidity 0.7.5;

contract MemoryAndStorage {

    mapping(uint => User) users;

    struct User{
        uint id;
        uint balance;
    }

    function addUser(uint idx, uint balancex) public {
        users[idx] = User(idx, balancex);
    }

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

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

//Swap “memory” out with “storage”.
}

1 Like

The easy solution was to eliminate a few lines and directly assign the new value. It does say ‘updateBalance’ versus ‘send’ or ‘add’ so I left the assign new balance versus adding it to the old.

The difference between the old/new version:

machine$ diff datalocation.sol datalocation-fix.sol
16,17c16
<          User memory user = users[id];
<          user.balance = balance;
---
>          users[id].balance = balance;

The resulting code…

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

Lol
I just change the memory to storage and the code worked for 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 {
     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] = User(id,balance);
    }

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

}

2 Likes

A solution is to avoid using a temporary memory variable and instead update the users mapping directly.

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

// one solution - access the dictionary directly. Tested.

function updateBalance(uint id, uint balance) public {
     //User memory user = users[id];
     //user.balance = balance;
     users[id].balance += 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