Data Location Assignment

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];//memory is a temporary storage, to get a persistent one, switch to storage. like here. I could update the balance with this.
         user.balance = balance;
    }

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

Thanks Capa

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 storage user = users[id];
user.balance = balance;
// uint balance = balance; doesn’t work
}

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

}

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

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

}

Update the balance of the user stored in the users mapping which is part of storage. That way it will persist between function calls:

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

The problem here is that there is a mismatch in terms of how the state variable ‘users’ is persisting users to the storage but the ‘user’ variable within the updateBalance function is only temporarily saving the value to memory (not persisting to storage). There are a few ways to fix this by either changing the user local variable in the updateBalance function from memory to storage OR by directly updating the users state variable. The second approach is more efficient:

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

Problem: A temporary variable was introduced to hold the user. Then, the balance was updated. But the temporary user variable was held in memory, so after function execution, the temporary user was deleted. Thus, the balance was updated on the user in memory, not the one in permanent storage.

My solution is to update the balance of the user from storage without even introducing a variable, which is completely unnecessary here.

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

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]; //This only update the balance of the local user, not the user in the state mapper
     users[id].balance = balance;
}

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

}

Need to change memory into storage in this part of the code

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

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

}

It seems like the updateBalance function is modifying a local struct variable created with the name “user”, which initially gets the same value as users[id]. Trying to change the value of this variable won’t affect the real user with the id (users[id]).

So, my suggestion is changing the function from this:

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

to this:

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