Data Location Assignment [OLD]

the topic didn’t exist yet, so I created it

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];
         user.balance = balance;
    }

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

}
11 Likes

@Capaburro thanks for making this thread

@filip I would suggest updating the forum link on the course slide to this thread

My answer

Change the storage type of ‘user’ within the ‘updateBalance’ function from ‘memory’ to ‘storage’. I believe this allows it to modify the variable value on a global level, rather than only locally within the function.

2 Likes

Thank you, I have updated it,.

2 Likes

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

}

1 Like

The problem was that the updateBalance function was only storing the new balance in memory and not storage. This caused the new balance to be lost as soon as the function completed executing. I have updated the function to store in storage via the mapping.

pragma solidity 0.5.2;
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;
}

}

1 Like

My solution

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];
         user.balance = balance;
    }

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

}

Just change memory to storage. You need storage
so that the amount is stored in permanent memory.

In the updateBalance function:

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

We should use “storage” as opposed to “memory” in order to have more persistent records of our update. Memory gets wiped as soon as we finish the function call.

1 Like

The problem with the function updateBalance(uint id, uint balance) is that the struct instance user is stored in memory which is volatile and so the value of user.balance is lost when the function call terminates. Two different ways we can fix the function are:

  1. by replacing memory with storage

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

or 2. by changing the value of balance in the mapping from id to balance in users since the mapping is a global state variable

function updateBalance(uint id, uint balance) public {
       users[id] = User(id, balance);
}
pragma solidity 0.5.1;

contract MemoryAndStorage {

    struct User{
        uint id;
        uint balance;
    }
    
    mapping(uint => User) users;

    function addUser(uint id, uint balance) public {
        users[id] = User(id, balance); //creating a user
    }

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

}

My attempt:

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

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];
     user.balance = balance;
}

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

}

Change memory to storage. The amount needs to be in storage
which is a permanent memory.

Ready!!!

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

We need to change memory for storage, because otherwise users[id] will be deleted once the function finishes running

Or modify directly the state variable :wink:

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

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

}

Hi @filip @everyone. Considering this potential solution:

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

Why does the getBalance function below seem to work even when the updateBalance function above doesn’t modify users[id].balance?

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

Because they have 2 completely different goals.

In the update function you want to make a permanent change to the user that is saved in the mapping. That won’t work if you’re only changing the copy you just made. You need to change the original mapping.

In the getBalance function, you are looking to return the current balance of the user. Then it doesn’t matter if that balance comes from the original mapping or a copy that you just made. The value is the same.

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

}

Hi there

pragma solidity 0.5.1;

contract MemoryAndStorage{
    
    struct User{
        uint id;
        uint balance;
    }
    
    mapping(uint => User) users;
    
    function addUser(uint _id, uint _balance) public {
        users[_id] = User(_id, _balance);
    }
    
    function updateBalance(uint _id, uint _balance) public payable {
        users[_id].balance = _balance;
    }

    function getBalance(uint _id) public view returns (uint) {
        return users[_id].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 {
    /* we have to insure that the data is stored in the persistent storage mapped by users[id] */
     users[id].balance = balance;
}

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

}