Data Location Assignment [OLD]

function setBalance (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 memory user = users[id];
     users[id].balance = balance;
}

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

}

1 Like

Change memory to storage.

1 Like

pragma solidity 0.5.1;
contract MemoryAndStorage {

mapping(uint => User) users;

struct User{
    uint id;
    uint balance;
}

addUser(updateBalance);
addUser.push (Users[id]);

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

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

}

I am not entirely sure if i have written the code exact, but my understanding is that there isn’t a .push function to save to the storage to enable updating?

I loved trying to work it out tho haha…

lol ok, clearly over thought this

1 Like

Change “memory” to “storage” so the updated balance is stored in the mapping and not forgotten once the function has been executed.

function updateBalance( uint id, uint balance ) public {

User storage user = users[id];

User.balance = balance;

}

1 Like

Hi @NetworkP,

Yes…your solution attempt is certainly creative! But, unfortunately, it’s too freestyle to work :wink:

You can’t pass a function to addUser because its parameters are defined as unsigned integer data types.

.push() is an array method, so you can only use it to push values to an array. I’m not really sure what you’re trying to push to here. You can’t push to a function, or a mapping, and the mapping has the name users, anyway, not Users.

Having watched the solution video, do you now understand how the problem is solved? I would encourage you to have a look through a selection of other posts in this discussion thread. There are several different alternative solutions, and you’ll find them all here, together with feedback, corrections, discussions and explanations :slight_smile:

Basically, we need to ensure that the updateBalance function body contains code that updates the balance stored in the mapping (permanent storage) with the new balance. We find a specific user instance in the mapping with the key (ID) using users[id]. Then we assign the new balance to that user instance’s balance property. I think this is most clearly shown with the following one line solution:

users[id].balance = balance;
/* .balance to the left of the assignment operator (=) references the
    specific user's balance property */
/*  balance to the right of the assignment operator references the new balance 
    value passed into the function (as an argument/parameter) when called.  

I’m very pleased to hear that, as this is very important! :smiley:

1 Like

Hi @mburtonshaw,

Your solution is nearly correct. You just need to make sure that you are assigning the new balance to the user (not User) variable. User defines the data type, user is the name of the variable.

Hello Burton. Thanks. I understood why balance wouldn’t update but rough around the edges implementing it haha…i find coding one of my weaker points of the whole course, but i enjoy it and so determined to make great progress before the end of 2020.

Thanks for your clarification, and yes, after going through the solution it is more clear in terms of understanding the code.

1 Like

:muscle:

If you carefully analyse the solutions and work out how they do what they do, then you’ll gradually find that you are able to come up with them yourself :slight_smile: Keep on persevering!

By the way I’m Jon, not Burton, but you can call me Burton if you like :joy:

1 Like

Lol. Sorry Jon. I will study your solution later tonight as i intend to brush up on my understanding.

Thanks and definitely here for the long haul.

Have a good night bro.

1 Like

One small change is necessary to make it work:

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

1 Like

I think that an erroneous part was working on a user that existed only within a memory and didn’t affect one within a storage. Simplest solution that i could find was:

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

1 Like

My step process. First I deployed the contract code as-is and realized the update function would not update. So I realized the issue was with that specific function. I inspected the code and my first initial reaction was that maybe I needed to use the (push) code but after analyzing the other codes we worked on I realized that wouldn’t work with this. So then my gut instinct was to just change memory to storage because that’s what Filip just taught us about and that worked.

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

The only necessary change was to change the memory term to storage to ensure that the data is saved to persistent storage not simply a temporary memory.

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

Hi @josephg,

Apologies for the late response to your question.

Firstly, it’s important to note that we can name a function whatever we want. So, before jumping to any conclusions, we would need to look at the code the function contains to see what it actually does, and also the content of the smart contract it forms part of, in order to understand the context within which the function is operating.

During this initial Solidity course, you are only coding smart contracts that deal with ETH, which is the currency used for paying for performing smart contract transactions (which could involve purchasing tokens, in an ICO, for example). The owners of a smart contract need to be able to manage the funds in ETH that their contract holds, and this would include the ability to withdraw funds, which after all are theirs. If the smart contract is managing ERC20 tokens and the withdraw function is only transferring ETH, then this can be perfectly valid.

The contract could also be a savings contract. If the contract owner is the saver, then obviously they need to be able to withdraw their funds.

Another valid use case for this type of function is when the owner needs to withdraw ETH in order to be able to refund a user who sent it to the smart contract by mistake (and who is now claiming it back).

Hopefully, you can now see that there are many possible valid use cases for an onlyOwner function which withdraws ETH, and why we need to make our assessment on a case by case basis.

I hope this goes some way to answering your question, or at least gives you some things to think about :slight_smile:

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{
     //Storage is forever so using storage keeps the data stored even after we're done with the function
     //User storage user = users[id];
     
     //Using memory only makes the value allocated stick to the user.balance as long as the function runs but not after the function is done
     User memory user = users[id];
     user.balance = balance;
     
     //users[id].balance was created outside the function, so calling it into the function realocates the value stored in storage
     users[id].balance = balance;
}

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

}

1 Like

ragma 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

yes, cheers Jon. Done that.

1 Like