Data Location Assignment

All I did was change memory to storage.

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

}
  • Changed memory to storage in the updateBalance function, changing storage location from memory to storage will not create a new copy of data, rather it will create a pointer to storage. Hence any change in user object will be reflected in the storage itself.
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 {
     
     users[id].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 {
         users[id].balance = balance ; // - answer 
    }

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

}
1 Like

Hi @jon_m. It took me a long time to make a reply on this comment of yours for honestly I didn’t understand it the first time. I’m very new to programming (only 3 months) so I needed to read a lot of documentations about solidity (the many words and its meaning). And it just made me realize I still really need to read more and practice what I read. Lol

Anyways, reading it again now, I felt like I need to say thank you for your explanation. It surely shed some light to my confuse mind. Thank you so much!

If there’s anything you can suggest that I read to fast track my learning that would be very much appreciated.

1 Like

Hi @gkassaras,

Valid points :+1:

I did actually look at the gas cost differences a while back, and changing memory to storage (and keeping 2 lines of code) was only very very slightly more expensive than the more concise one line  contractUsers[id].userBalance = newBalance; However, as you predict, the gas cost is exactly the same with optimization, which makes sense as both versions are essentially performing exactly the same operations. So, I think it’s more down to personal style, and also, as you say, which one allows easier debugging, code auditing and so, ultimately, more security. And having had a look at your profile, I can see you’ve had many years of experience in program security, security testing, security assurance and risk assessment. So thank you very much for your input, comments and well-reasoned opinion about the alternative solutions to this exercise from a security and assurance point of view — it makes for a more interesting and thought-provoking discussion.

If we change the functionality of the addBalance function to add an amount to a user’s existing balance (instead of replacing it with a newBalance), do you not think that it would be clearer to rename the function deposit (or similar) and rename the parameter newBalance => amount (or similar)? We are adding an amount to an exisiting userBalance to create a newBalance, rather than adding the newBalance to the exisiting userBalance. Obviously, the assignment operator = or += makes it clear whether we are adding or reassigning, but don’t you think that this is also better reflected in the names we choose as well?

Nice solution, and great question @Stequal :ok_hand:

This line isn’t making a copy or saving any new data in persistent storage. Instead, it creates a pointer (a reference) to a specific User instance in the users mapping — the one which has the id parameter input into the function as its key). This means that when balance is assigned to user.balance in the second line it is effectively being assigned to users[id] in the mapping. This means the update is made to persistent storage, instead of just being saved temporarily in memory within the function until the function finishes executing.

So, no — this code doesn’t save every updated balance as separate values within persistent storage. Instead, each time the balance is updated, the exisiting balance is overwritten with the new one (the value is reassigned).

In terms of comparing the efficiency of different alternative solutions, have a look at the following 3-post discussion, which I think will get you thinking about the different factors that need to be considered:
https://forum.ivanontech.com/t/data-location-assignment/27990/17?u=jon_m
https://forum.ivanontech.com/t/data-location-assignment/27990/20?u=jon_m (reply to previous post)
https://forum.ivanontech.com/t/data-location-assignment/27990/31?u=jon_m (reply to previous post)

Let us know if this answers your question, and if it gives you a better understanding of what the code is actually doing :slight_smile:

Nice solution @alve_lagander :ok_hand:
… and welcome to the forum! It’s great to see you here, and I hope you’re enjoying the course :smiley:

Hey @zai,

Don’t worry about not replying straight away! I know that sometimes we first need to take some time to think things through. Also that’s normal to not understand everything when someone explains things to you for the first time. You shouldn’t let that slow you down too much, because, as long as you read things over a few times and try to understand as much as possible, then you will find that the more difficult concepts do eventually make a lot more sense later on. I sent you some quite detailed comments because you had put a lot of effort into attempting to explain what the code was actually doing in this assignment solution. This is a great way to learn, because even if your explanation isn’t quite right to start with, the main thing is you are getting your brain used to thinking about things in a certain way. It also makes it easier for someone else to see what it is that you understand, and the things you need more help with.

In terms of additional reading material it can be difficult at first because a lot of the documentation, information, and articles about Solidity can be quite confusing for beginners — especially because of all the new terminology. That’s one of the reasons why I really recommend that, after completing an assignment and posting your solution, take some time to study some of the other student posts in the same thread, and try to understand the solutions that may be different to yours. There are often several possible alternatives. You will also learn a lot by reading through some of the comments and feedback posted here. Some may not make sense, but some will provide you with useful additional information, get you thinking a bit more deeply about what you’ve just learnt, and it’s also a good way to start getting used to reading about code, understanding the terminology, and also to practise reading and understanding the code itself. You should also have a look at the general discussion thread that comes with each section of the course. You will find lots more useful information and comments here, and it’s also good to see the sorts of questions other students are asking. Another good way to learn is to start posting your own questions, and when you get more confident, if you know the answer to someone else’s question, try answering that as well.

Another good piece of advice is not to rush too quickly through the courses. Take your time, spend time doing your own research, and experiment with the lecture and assignment code in Remix by reworking it, adapting it, and extending it.

Apart from that, just doing a search using keywords about something you want to understand better will often give you links to Question & Answer Knowledge Sharing Sites such as Ethereum Stack Exchange or Stack Overflow, which can be difficult at first, but once you get used to scanning and finding information that makes sense to you, this can be an invaluable source of information and example code. When searching, you’ll also often find Medium articles in the search results. Some of these can be really good, but just be aware of when they were written (see below about older/newer versions of Solidity)

The other thing I really recommend is finding some good YouTube channels about Solidity. A very good one that I use a lot for reference is:
https://www.youtube.com/c/EatTheBlocks
Have a hunt and find some beginner tutorials first to see how useful and helpful you find them. I often look for this channel’s videos when I’m doing a search about something I would like to find out more about. You need to be careful about the version of Solidity used in each video though, as many of the beginner ones will use older versions. This isn’t a major problem if you are just using them for a general introduction and extra information for different concepts, but you need to be aware of it. You can then check with more detailed documentation to see if later versions have implemented any changes. This channel also has some good videos summarising the main changes that have been implemented with new versions.

Finally, the most comprehensive documentation for Solidity is:
https://docs.soliditylang.org/en/v0.7.5/index.html
This is a link to the documentation for version 0.7.5, the version you are using in this course.

I think that’s enough information for the time being! :muscle:
I hope you find it helpful and inspiring! :grin:

1 Like

@jon_m Thank you really for taking some time answering my request! I usually have information overload when I search the net about solidity and it’s exhausting most of the time. I’ll just take one step at a time.
Yes, I totally agree that it really helps reading the answers of others. Hopefully, time will come that I wont be just reading answers but will start giving them soon and help out.
Will definitely check out the links that you provided. Thank you so much again!

1 Like

I got the point but I have difficult in writing the code. The codemap is the following:
1 – User ID and balance are saved in the storage
2 – Amount to send or to change is saved in the memory
3 – New balance is calculated and saved in the memory
4 – New balance will replace balance and saved in the storage
Is anything wrong in my mental map?

1 Like

In the original code, the problem is that we are creating a memory variable, and modifying it, so it will be deleted once the updating function is finished.

We have to use “storage” instead:

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

Another solution would to use the memory user object, and then saving it in the users dictionary, but the first solution commented sounds better for me.

1 Like

Hi @cincinnato, hope you are ok.

Now to graps the concept on storage and memory for Solidity it could be confusing.

To keep it on simple terms, think on memory has a volatile memory like RAM in pc. Meaning is a memory space that will only be used for the function operations, after it finish its execution, some values can be deleted.

While storage is more like saving data directly in the hard drive, but in this case is the blockchain, so basically is: if you need to save data permanently in the blockchain, you use storage.

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.

Sorry Carlos, I think you confused points in your explanation, as it should be exactly the opposite. Memory is temporary data location and storage is persistent data location. For your reference I enclose the screenshot of the lesson where stated.

These points are very easy to understand. The problem is another one. It is not easy for people not used to write code to assimilate these concepts in the code lines. I have already seen the solution video lesson and I got it, but if I should understand in the code lines… well this is very hard, at least for me.33 - Data location

1 Like

My basic solution:

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

}

QUESTIONS:

  1. Why can we use our struct “User” in the map “users” before having declared this struct???
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 balance) {
    return users[id].balance;
}

// I used storage instead of memory - it seemed to have worked

1 Like

My solution to the Data Location assignment

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

}

seems to be working the way it should now.

Ben

1 Like

I may be wrong, so please correct me if so, however I think that the “User” in the mapping is just the value Type. It is just stating the type of value that will be in there, not actually declaring/defining anything yet.

Ben

1 Like

Yes, my bad, I got it backward from my notes, fixed now.

Indeed it is the most hard part, but the more you program, the more easiest will be for you to understand code quickly.

Carlos Z

Remember that all code from your contract will be compiled into byte code at the end, this means that all the contract logic will be available at the execution time no matter the order.

But it is a good practice to keep your syntax easy to read and understand has possible.

Carlos Z

1 Like