Data Location Assignment [OLD]

Hi

I updated the updateBalance function so it stored the ‘user’ data in ‘storage’ rather than ‘memory’ so it is retained after the function has completed its job.

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

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

}

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

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

}

User memory user = users[id];

It seems that having memory as data location also means that you are creating local copy of variable even when referencing object from storage data location. Any operation on copy will have effect on copy only.

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 {
         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.5.12;

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 {
         return updateBalanceSimple(id, balance); // works
         // return updateBalanceUsingStorage(id, balance); // works also
    }
    function updateBalanceSimple(uint id, uint balance) private {
         // User memory user = users[id];
         // user.balance = balance;
         users[id].balance = balance;
    }
    function updateBalanceUsingStorage(uint id, uint balance) private {
         // User memory user = users[id];
         User storage user = users[id];
         user.balance = balance;
    }    

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

Nice solutions @Laurenzius, and nicely set out within separate functions called from updateBalance :ok_hand:

Just one observation: it still works, but the return keyword in updateBalance is redundant and can be removed. This function isn’t returning anything, it’s just calling another function. In Solidity, the return keyword will only return something if you also have returns() in the function header.

1 Like
Summary

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

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

}`

1 Like

Nice solution @ElyRamos :ok_hand:

If you use the alternative solution (changing memory to storage) you still need the 2nd line of the original code, because that assigns the new balance to the user’s record stored in mapping using the pointer created in the 1st line (user) i.e.

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

// Data Location assignment
pragma solidity 0.5.12;
contract MemoryAndStorage {
mapping(uint => User) users;
struct User{
uint id;
uint balance;
}
constructor(){

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

}
// added storage to file as way of getBalance from global perspective
// Local variables of struct, array or mapping type reference are stored in storage by default.

1 Like

just change the update function with following body:

     users[id].balance = balance;
1 Like

Change updateBalance

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

Good to see you back here in the forum @Bdigger :smiley:

Your modified updateBalance function is correct :ok_hand:

In order for your full smart contract to compile, you need to remove the empty constructor (which isn’t needed) and add view to the getBalance function.

Changing memory to storage creates a pointer to users[id] (to the User instance for that specific id in the users mapping). This means that the new balance can then be updated permanently in the mapping, and not just temporarily to a local variable.

You’ve got confused here…
… Local variables of type struct, string, or which are arrays (e.g.  User memory user  in the initial version) are not located in storage by default. We have to specify either memory or storage by adding these keywords.
It is all state variables and mappings which are located in storage by default.

I hope that’s made things clearer. Just let us know if you have any questions :slight_smile:

Appreciate feedback thanks

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

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

}

1 Like

Remix gives me an error when I tried that… :thinking: Doh!!! I had typed user instead of users :crazy_face:

1 Like

I noticed the updateBalance function was creating a copy of the user from the users mapping and saving it in memory, so I changed it to affect the user in the mapping itself:

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

pragma solidity 0.5.1;
contract MemoryAndStorage {

mapping(uint => User) private 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