Data Location Assignment

Yoooo! Glad to see you’re making such great progress Xyz! The projects in this course are a lot of fun.

I just finished the final project (well, my first functional draft) and I will tell you: it was challenging. I ended up having to dive back into this Data Location lecture to solve some errors I was having, but patience & determination got me there!

Good luck out there, keep it up!!

2 Likes

Thank you for the vote of confidence man! I’m amazed to know that you finished the final project (I don’t know what that is yet though :sweat_smile:). Keep doing an awesome job man!!

p.s. The JavaScript course helped a lot for me to understand this course, without this I would be lost haha

2 Likes

The problem is caused by the use of memory instead of storage. When using memory a copy of the user is assigned to the variable and is erased once the function is complete. Therefore, by changing memory to storage, the actual memory address of the variable is changed.

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

}

If you use memory , then you’re making a copy of the struct in memory and then updating that. If you use storage , you’ll get a reference to the struct in storage, so your modifications will be persisted.

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

}

1 Like

Hey I only changed memory to storage on line 16.

From my understanding using memory lets the function be mutable and storage makes it point permanently to the user.

Screen Shot 2021-04-01 at 12.02.45 PM

2 Likes

Hey,

I just change the equal sign to += in the updateBalance function and set up a storage as a storage data type for user.

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{
        User storage user = users[id];
        user.balance = balance;
    }
    
    function getBalance (uint id) public view returns (uint){
        return users[id].balance;
    }
}
1 Like

My solution:
changed line 16: memory --> storage
The user is used in other functions, it has to be permanent.

Code:

pragma solidity 0.8.3;
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.0;

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

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

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

}

I added this line
function updateBalance(uint id, uint balance) public {
users[id].balance = balance;
}
Not sure how to check if the key exists in the mapping but the logic would be updateBalance will not only update a balance for an existing address but create a new balance for a new address if it doesn’t already exist.

1 Like

we should call the user from storage and not memory, memory storage is temporary.
So we change the 2nd line in the updateBalance function to:

    function updateBalance(uint id, uint balance) public {
         User storage user = users[id];
         user.balance = balance;
    }
1 Like
type or papragma 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];                                 *Replace "memory" with storage*
         user.balance = balance;
    }

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

}
*Replace "memory" with storage* as its not being saved to storage when using memory variable
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
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 {
        
        uint previousBalance = users[id].balance;
        
         User storage user = users[id];
         
         user.balance == balance;
         
         assert(user.balance == balance);
    }

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

}

You said update ballance. soooo, i update the ballance to the number that i write, not write.

1 Like
     //require(msg.sender == owner);  Check if the caller is the owner
     //User memory user = users[id];
     //user.balance = balance;
     users[id].balance += balance;
1 Like

Since the users mapping is essentially a state variable, it is of type storage. Therefore the setter must also refer to it as a storage variable.

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 initially solved this by changing ‘memory’ to ‘storage’ since memory would not persist outside the function scope.

After reading through different solutions I realized I didn’t really understand the alternate method changing users[id].balance = balance so I reviewed my code until I better understood how mapping and struct were related (User, the struct vs users, the variable referenced to access data within the struct mapping).

I updated my code from my initial solution to the one below as I believe it’s much more elegant.

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

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

}

1 Like