Additional Solidity Concepts - Discussion

data location assignment

changed

User memory user = users[id];
to
User storage user = users[id];

1 Like

Don’t store the balance in a local variable where it gets wiped, but put it into persistant data
remove:
//User memory user = users[id];
//user.balance = balance;
add:
users[id].balance = balance;

1 Like

Hi guys… very new to programming and apologies for my ignorance. I don’t understand why in the function below:

function addUser(uint id, uint balance) public {
users[id] = User(id, balance);
}

users[id] takes on two parameters and not one. also please correct me if i’m wrong here, but is [id] a newly introduced variable, and not from

struct User{
uint id;
uint balance;
}

Getting confused…

2 Likes

Hey @Yutaro_Shimizu, hope you are ok.

You are forgetting about the array, which is users (which is based on the struct).

In the addUser function, It adds the id and balance values based on the User struct to the [id] on the users array.

Hope i expleined myself good, if not let us know :nerd_face:

Carlos Z

1 Like

Topic: Events
Not sure if this is the correct place to post this, but I’m sure peoples will let me know;

I have tried to add an emit function for transferred as Filip advised us to try,

image

However, for some reason I am getting the below error code in the console,

image

Can anyone advise?

Hi @Andre_Mark,

Your transfer event declaration is correctly coded. However, notice that the transfer() function executes a transaction that involves 2 user addresses (the sender and the recipient). This is different to the addBalance function, which executes a transaction that only involves 1 user address (the depositer). So, in the transfer event it would be useful to include the sender’s address, as well as the recipient’s address.

There are a couple of issues with your corresponding emit statement:

  • You have declared your second parameter in the transfer event with the name transferredTo, but in the emit statement the second argument is referencing msg.sender, which is the address the transfer is being made from (not to).
  • The event should only be emitted once the event itself has been executed, because the logged event should act as confirmation that the event has ocurred. Therefore, we usually place an emit statement at the end of the function which emits the event (but before any return statement).

The error message appears to be telling you that you’ve called the transfer() function with only one argument. It expects the first argument to be an address, but it looks like you’ve input an integer of 500. That’s why it’s telling you that the address is invalid.
The transfer() function has 2 parameters: an address (for the recipient of the transfer), and an unsigned integer (the amount to be transferred). Therefore, in the transfer function’s input box in Remix, you need to:

  1. input an address: choose one from the Account field dropdown, copy it to the clipboard, and then paste it into the input box;
  2. add a comma (arguments need to be separated from each other by a comma);
  3. input an amount;

Alternatively you can click on the down arrow next to the input box and you’ll get a separate input box for each argument. If you use these you don’t need to add the separating comma.

Post your corrected code in the Events Assignment discussion topic, and I’ll take a look at it :slight_smile:

Just let me know if anything is unclear, or if you have any questions.

@filip Is there a tool or a way to view the state storage content of a specific smart contract? (with no code)

E.g., I want to see all the mapping content of balances in a specific token without using APIs or functions?

And where is the storage of these state storage? is it in the blocks? Can you guide me here to understand the internals of how the node store the state and the location of the storage?

Thanks

Hey @mohkanaan, hope you are well.

It must be through a dapp (code require), here is an example of a dapp that tracks the DAI Stats (the DAI contract stats) https://daistats.com/#/

Impossible, unless the contract store publicly all the addresses that have a balance with the contract, remember that mappings are key to value storage, meaning that you need to know the key to get the value of it, if the contract does not have a public function to get all the addresses, is impossible to know how many keys contains a value on the mapping.

This will require an extensive learning on the nodes, how do they work and how the data is storage on files that we call “blocks”. You might have to research it by yourselve :face_with_monocle:

If you are looking to build a dapp that can have features like tracking the balance of an address on multiple protocols, you might wanna take a look at https://moralis.io/ (JS programming require).

Carlos Z

1 Like

Thanks @thecil for the answers, but I still need to know the mechanism of how the key-value state storage is stored in the blockchain; unless there is encryption and we don’t know the decryption key, there must be a way to view the content of the storage without using smart contracts/solidity code (I mean here using a code connected to the blockchain directly and not through EVM)

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

}

1 Like

Hey filip,

In the update balance assignment when I deploy the contract and interact with it it actually never updates the balance? I first add a user and balance then updateBalance (change the balance) get balance but still show me the previous balance? not sure what I’m doing wrong…

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

1 Like

Hey @berto, hope you are ok.

Would be great if you can provide your entire contract in the following way so i can review it :face_with_monocle:

Carlos Z

Hey Carlos, thanks for your reply please find code bellow and screenshot thanks!

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

}

remix

1 Like

Hey @berto, hope you are well.

Your contract does work correctly from my side (I deployed it on remix), I think the problem you have comes from the way you are inputing the values to the contract functions.

like updateBalance, you just pass: 1,20000. Which should be “1”, “20000”. Or open the function fields and fill each normally.

image

Carlos Z

Okay, well before I solve this code, I’ve a question about using Remix IDE:

The Remix UI I’m using looks somewhat different than the UI in the video, and I’m not clearly seeing where the values (user Id, balance, etc) are represented whenever I execute a function. I read what is in the terminal, but it does not appear to show any data values being changed, nor do I see this anywhere else in the Remix UI. Hard to fix a problem if I cannot see the results of computations.

Sometimes I see values under the function UI buttons, but sometimes not (???)

How can I see the data values?

Okay I figured out the UI enough to see the data.

Although I’m still wondering how I can see data in the transaction records in the terminal ?
Is it there, but just in hex code?

I’m very happy to see that Solidity includes an event-based programming paradigm.

I was a Flash/ActionScript programmer for more than 10+ years, and I got very used to event-based programming … well before I got into JavaScript or anything else. So I’m enthused to get back into event-based programming with Ethereum smart contacts!

Questions:

1 - emitting an event can also be listened to within a contract AND by other contracts or dApps?That sounds really powerful and full of interesting potentials. I want to learn more about this!

2 - does indexing event data to nodes increase the gas of a contract execution?

3 - by indexing, does this mean that the event data is written permanently into the Ethereum blockchain? if so, then NOT indexing means that data within a contract is never really publicly available … with the exception of token transfers (which are inherently logged on the blockchain?). Correct? I’m just really trying to understand what this indexing really does …

4 - does indexing contribute to on-chain market analysis?

5 - from the Events Quiz, it seemed to me that maybe all 3 of these answers may be correct (?). I’m the least, I thought I heard Fillip say that external contracts and dApps can listen to a contracts events? So isn’t that answer true also?

image

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.5.7;

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