Ok, so is your solution just the 3rd line in the updateBalance function body? i.e.
function updateBalance(uint id, uint balance) public {
users[id].balance = balance;
}
Also, please don’t post screen shots of your assignment solution code, because the code can’t be copied and pasted into a text editor for executing and testing purposes. Thanks
This was my first solution, but after reviewing the communities responses, it seems like mine works but wasn’t dry enough
Realized I could have just updated “User memory user = users[id];” to “User storage user = users[id];” which would have cancelled out the need to add “users[id] = User(id, balance);” to the updateBalance function.
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(id, balance);
}
function getBalance(uint id) view public returns (uint) {
return users[id].balance;
}
}
I’ve missed this replay! sorry for the late answer and thanks for it! I did the solution to the assignment right and I did the previous post just as an exercise. That is clear to me.
I’ve still some doubt about this code:
User storage user = users[id];
user.id = id;
user.balance = balance;
doing so I assign users[id] to user and the problem is that user is empty (because the function didn’t assign id and balance yet to it) ?
Also I don’t understand why it works if it is wrong.
Sorry for the long reply and thanks for your patience!
Assigning users[id] to user isn’t wrong, it’s just unnecessary/superfluous if user is defined as a local variable in memory (instead of storage). This is because, whether this is a new person or an update to an existing person, this new or updated User instance still needs to be saved to the mapping located in storage after the ID and balance data have been assigned in the 2nd and 3rd lines, as follows:
users[id] = user;
In summary: this is one possible solution
function updateBalance(uint id, uint balance) public {
User memory user;
// User memory user = users[id];
// this still works ok, but it's unnecessary/superfluous
user.balance = balance;
users[id] = user;
}
If we change memory to storage, then assigning users[id] to user isn’t wrong at all, in fact it’s necessary in order to establish user as a “pointer” to the users mapping i.e. whatever is assigned to user within the function is automatically stored within the users mapping.
In summary: this is another possible solution:
function updateBalance(uint id, uint balance) public {
User storage user = users[id];
user.balance = balance;
// users[id] = user;
// this last line now isn't needed as the 1st line performs this assignment
}
So, hopefully, you can also now see that in this second solution, if user now points to the same User instance in the mapping as users[id], then adding a user variable is actually an unnecessary intermediary step, which we can cut out, and we can just combine the first two lines as follows:
function updateBalance(uint id, uint balance) public {
users[id].balance = balance;
}
I hope that helps to clarify things for you. But just let us know if you have any further questions
pragma solidity 0.5.12; // Updated the soldity version
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;
// As data in 'memory' is lost after function is exited, the data will not update global
// mapping, so to update the mapping, I added the following line:
// users[id] = user;
// However I noticed that the Gas cost with this change, was quite high, so I decided
// to update the global mapping directly, which brought the Gas cost down.
users[id].balance = 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 {
require(id > 0); // added to check input because we dont want any zero ids
users[id] = User(id, balance);
}
function updateBalance(uint id, uint balance) public {
require(id > 0); // added to check input because we dont want any zero ids
require(users[id].id > 0); // added this to make sure user exists -- This code will prevent user from creating a new user, must use addUser for that.
//User memory user = users[id];
//users[id].balance = balance; // this is the problem right here - this var is not in storage area.
users[id].balance = balance; // added this to fix the problem: update the persistant storage
}
function getBalance(uint id) view public returns (uint) {
return users[id].balance;
}