Do I understand correctly that all emitted events are logged to the blockchain? If so, is that a relatively expensive operation?
Hi @letscrypto,
The emitted events are logged in the transaction data. You can see the log created in the transaction detail, by clicking on the arrow next to the transaction confirmation in the panel below the code editor in Remix. My understanding is that all of this transaction data (including the event logs) are hashed and then included in one of the mined blocks. However, event data is not stored in smart contract state variables and so this reduces their cost in terms of gas. As well as being part of the transaction hash, which becomes an immutable part of the Ethereum blockchain, the actual raw (unhashed) event log data is also stored in the nodes as part of the transaction receipt. This is the event log data which can then be accessed by the dapp for end-user display, data analytics, and data management purposes.
Again, Iām tagging @gabba so that he can add any further clarification, or correct any inaccuracies in my explanation.
These contracts are on the EVM which is blockchain correct? This section dealt with ādeletingā a person or address. How is that possible due to immutability? Or is it just how it is named? Is it actually āinactivatingā this person as they are not really deleted?
The reason I bring this up is an accounting program I used over the years called Simply Accounting you could not delete anything, you reverted transactionsā¦but there was always a record which I think is a concept of true accounting.
Then came along Quickbooks which was easier to learn. In this program you could actually delete accounting events altogetherā¦as though they never happened at all.
This is the life experiece comparison I make to EVM and the ādeleteā person.
@filip first and foremost, thank you for the great lessons!
I tried googling for the precise explanation on why we donāt need to tell the location when defining a parameter in a event, but couldnāt find anything, so I just wanted to give a slight contribution on why I think this is the case, since you mentioned youāre not sure
It makes sense that we donāt have to specify the location for the event parameters because the definition of the event is pretty much just an abstraction (you can see it doesnāt even have a method body for example). When you emit the event, itās just going to send whatever information you provided to any subscribers, so it doesnāt really matter if this information is coming from memory, storage, or anything else for that matter, because this information is directly available during the execution of the method in which youāre emitting the event. Also, I think if somehow we could specify āstorageā as a location in a event for example, this could lead to some problems, because then this would mean that any subscriber of that event would be able to modify information that is internal to the contract without calling any of the contract methods, and I also donāt think itās possible to do something like that, technically speaking
question from quiz
" When is the function modifiers code executed?"
why the answer āwhen called by the functionā is wrong?
isnāt it like a function called at beginning of the main function?
Hi @sajede.k,
Apologies for the delay in replying to your question.
I must admit this question is a bit confusing, and maybe isnāt worded as well as it could be. Have a look at Filipās reply to the same question already asked by another student (always check the discussion thread to see if someone has already asked the same question and had it answered
So, I think you are correct thatā¦
ā¦ itās just that the correct answer is emphasising the fact that the modifierās code is executed from the function header, which is actually before the functionās code block is executed.
I hope that clarifies things, and confirms that both answers could in fact be considered correct, depending on how you interpreted them.
thanks for advise and explanation.
My solution, which appears to work in testing:
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].balance = balance;
}
function getBalance(uint id) view public returns (uint) {
return users[id].balance;
}
}
Hey Filip,
There is a discrepancy between the video and the code on github.
I expect you did this deliberately to keep us awake!
In the code its:
emit personDeleted(name, senior, owner);
In the video itās:
emit personDeleted(name, senior, msg.sender);
This is the version that works.
Donāt ask me why, Iām just a student.
When do I get to build my crypto!
DOODESVILLE
Hello Community!
Iām sorry if the topic was already covered above or if itās for another section, but couldnāt find it so:
If I understood correctly, Filip mentioned in one of the videos that itās not a good idea to use references like this
Person person = people[something];
person.property1 = newValue;
ā¦some other modifications on person
people[something] = person;
Could you please confirm if thatās correct and elaborate me why is that so? @jon_m
Hi Rusko,
This may refer to the Data Location Assignment, and the following possible solution (one of several alternatives):
function updateBalance(uint id, uint balance) public {
User memory user = users[id];
user.balance = balance;
users[id] = user; // added to update mapping
}
This is a very long-winded way of achieving the desired result. There is redundant code, and it is more costly on gas.
On the 3rd line of the function body, the value held temporarily in the local variable (user
) is assigned to the mapping (users[id]
). There is therefore no reason to also assign the data initially held in the mapping (referenced using users[id]
) to the local variable (user
) in the 1st line when defining it. If we are going to use a local variable stored in memory, we can simply define it initially, on the 1st line, as:
User memory user;
However, creating a separate local variable in memory still uses more gas than just changing memory to storageā¦
User storage user = users[id];
user.balance = balance;
ā¦ because this code doesnāt actually create a separate variable, but instead establishes a reference (a āpointerā) to the User
instance stored in the mapping, and then uses this pointer to assign the new balance to this User
instance in the 2nd line. In fact, this solution can also be made more concise as follows:
users[id].balance = balance;
This performs exactly the same operation, achieves the same result, and consumes the same amount of gas as the two-line solution using storage
above. You can read more about
the reasoning and logic behind this here.
I hope this helps to clarify the issues, concepts and considerations with this code.
Just let us know if you have any further questions about this.
Hello all. Thanks for being here.
Accidentally posted my solution here instead of the correct place. My badā¦
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;
}
}
Changed to storage.
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;
}
}
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;
}
}
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;
// you could also just directly write users[id].balance = balance;
}
function getBalance(uint id) view public returns (uint) {
return users[id].balance;
}
}