Hey @alegarap
You can initialise it outside the constructor although the best practice is to initialise your variables inside the constructor.
The only things that have to be initialised during the declaration are constant.
Cheers,
Dani
Hey @alegarap
You can initialise it outside the constructor although the best practice is to initialise your variables inside the constructor.
The only things that have to be initialised during the declaration are constant.
Cheers,
Dani
Thanks for the response!
Hi everyone, could someone please be so kind and and in simple terms explain what the abi.encodePacked is I am assuming it has to do with the keccak256 encryption or am I wrong?, Please advise. I really enjoyed the mapping and error chapters but when you get curved balls in the mix like abi it just get very frustrating.
Thx,
Hi Filip, could you please be so kind and and in simple terms explain what the abi.encodePacked is, I am assuming it has to do with the keccak256 encryption or am I wrong?, Please advise. I really enjoyed the mapping and error chapters but when you get curved balls in the mix like abi it just get very frustrating. Otherwise Iām really enjoing this course. Good work filip
Thx,
Hi @NLUGNER,
In Solidity we cannot use the == equality operator, on its own, to compare 2 string values (like we can with integers and Booleans). However, one way we can perform this operation is to first use the keccak256 and abi.encodePacked functions together. Firstly, abi.encodePacked converts the string into a hexidecimal number. Then, keccak256 creates a hash of that number. We can then compare these 2 hashes with the == operator. abi.encodePacked will also convert multiple values into a single hexidecimal number, making this method also suitable for comparing multiple properties of 2 struct instances. At first, I wasnāt sure why we canāt just compare the 2 hexidecimal numbers generated by abi.encodePacked. My understanding is that we also hash these hex numbers with keccak256, because this will always generate 2 fixed length hash values and so prevents excessive gas costs. I think that by hashing the values we are comparing, we also ensure that the same set of values (or the same sequence of characters in a string) will always evaluate as being equal to each other, because the same values will always produce the same hash.
This is the way I have come to understand this. Iām also tagging @dan-i and @Alko89 as they may be able to add more detail as to the reason why we canāt compare string values in Solidity using only the == operator. Hopefully, they can also confirm and/or clarify the reasons Iāve given for using keccak256 as well as abi.encodePacked.
Thank you very much for the clarification. Much appreciated and fully understood.
Best Regards and have a great day in the academy.
Nils
Iāve noticed that itās easy to loose brackets of any kind when ide in Remix isset to dark instead of a light background. Itās much easier to follow the code when using a light backgroun. You can change the theme in settings by clicking the cog wheel bottom right column. This is only my opinion. We are all different,
what does it mean when we say assert consumes all the gas remaining in the function?
Hello,
when we delete a person using function deleteperson, the address remains in the creators array, but it shouldnāt. I mean person 1 for example is deleted from people mapping, but his address is stored at the creators array as the creator 1. when we create a new person it should replace the deleted one but creators array doesnāt refresh.we need to delete the element in the deleteperson function but i donāt know how to address the corresponding index. is it okay to search the creators for the given address?
Hi @sajede.k,
Take a look at this post. It should answer your question. Let us know if anything about this is still unclear.
But we set cost in the code,how is it possible? Does it get back money to sender?
Hi @sajede.k,
I think you are confusing the following two different ācostsā:
Gas costs (transaction + execution costs) which are the computational costs charged for running the smart contract on the Ethereum network (the EVM), and which will go to the miners as block rewards. These costs are charged by the network.
Cost of payments coded into the smart contract, and required to be paid by theāmsg.sender
āin order to be able to invoke certain functions and execute specific transactions. This is the cost assigned toāmsg.value
and, when required, is paid by theāmsg.sender
āin addition to gas costs. These costs are charged by the smart contract.
When we are talking about the effects on cost of either require or assert failing, then we are talking about gas costs charged by the network, and not the cost of any additional payments charged by the smart contract.
I hope that clarifies things. Let us know if you have any further questions.
Thanks for explanation.
Hi again, @sajede.k
Apologies for the delay in replying to your question about deleting the address from the creators array.
Your question is a very good one, but there isnāt a straightforward solution. In fact itās quite involved. You need to iterate through the array and find the address of the person youāre deleting. The complication is that if you then just delete it, you will be left with an empty element at that index. All of the other addresses wonāt automatically shift down one index to compensate. If you want to do this (i.e. shorten the array by one for each address deleted) then you need to save the index to a local variable. Then, you need to iterate through the array again from the index of the deleted address, shifting each element down one index. Then finally, you need to reduce the length of the array by one, as, again, this isnāt done automatically. The following code is my solution to this, and following that Iāve linked to a discussion thread and a video which contain helpful background information about the methods used. I hope this answers your question and you find it helpful and interesting Let us know if anything is still unclear. I think this is a good example of why mappings are generally easier than arrays to work with in Solidity!
function deletePerson(address creator) public {
require(msg.sender == owner, "Caller must be owner");
delete people[creator];
uint index; /* Defines local variable to store temporarily the index
of the address to be deleted */
for(uint i = 0; i < creators.length; i++) { // Iterates through array
if(creators[i] == creator) { // to find address
index = i; // Assigns index to local variable
delete creators[i]; // Deletes address from array
break; // Exits loop when address found and deleted
}
}
// Iterates through the array from the index of deleted address
for(uint i = index; i < creators.length - 1; i++) {
creators[i] = creators[i + 1]; // Each element shifted down one index
}
creators.length--; // Length of array shortened by one index number
assert(people[creator].age == 0 && people[creator].height == 0 && people[creator].senior == false);
}
Hello,
I really appreciate your help. Thank you.
it was really complete and helpful.
is it a real case? because I suppose it will end up really expensive with all these lines of code and iterating
Hi @sajede.k,
Glad you found it helpful
You are right that the gas costs may be high, but it all depends on how important the operation is, and whether the contract owner is prepared to pay those costs i.e. youād need to think about cost v benefit. If there isnāt a cheaper way to perform the same operation, and the operation is a necessary one, then there would be no alternative other than to pay whatever the gas costs are.
The reason why the array of addresses was included in the first place, was just to keep a record for the contract owner of all of the addresses of users who have created a new person instance. The idea is that the owner only needs to know the index number where that personās address is stored in the array, in order to be able to retrieve the much longer address from the getCreator function. The address can then just be copied and pasted into the deletePerson function call as the argument. That particular person can then be deleted from the people mapping when the function is invoked. So, I would suggest that the addresses of deleted records donāt actually need to be removed from the array, because we want each person to have a different index number anyway, as this is acting as a unique reference number.
Without testing it, Iām not sure what the gas costs are, to be honest. If you are interested you can find this out for yourself by clicking on Debug next to the transaction report (bottom right), after calling the deletePerson
function. This will open the Debugger . You can click forward through the different operations contained within the deletePerson
function until you get to the first one associated with the code you are testing and want to know the gas cost for (you will know when you get there because the associated code is highlighted). As you then click through all the operations associated with that particular piece of code, you will notice the different amounts of gas used for each operation. I add up all these amounts to get the total gas cost of executing a partiular piece of code.
Thanks for the explanation. Iām so grateful.
Hey, youāre welcome @sajede.k,
Iāve just had a look at the gas costs as I was curious
To be honest with you, Remix seems to generate some odd results for gas, and in the past Iāve also been told by one of my colleagues @gabba, that the gas costs shown in the transaction reports in Remix arenāt accurate. These seem to be stated in wei and Iāve noticed that the transaction gas cost is the amount of wei deducted from the function callerās address in the dropdown account section in Deploy & Run Transactions.
I think youāll get a more meaningful comparison of gas costs by looking at the Debugger, as I mentioned earlier. What Iāve done is deployed the same contract in Remix both with and without the additional code in the deletePerson function (the code I came up with to iterate through the array, find the address and delete it). Then I created a person, got the owner to find the address by calling the getCreator function with index 0 as the argument, and then finally got the owner to call deletePerson both with and without the additional code. In the Debugger, instead of adding up all of the individual gas amounts for each operation associated with the additional code, as I suggested before, Iāve found that you can just jump to the end of the transaction and find the figure for gas remaining after all that transactionās op codes have been performed. If we always leave the Gas Limit in Deploy & Run Transactions as the default of 3,000,000 wei then:
Gas Limit - gas remaining = gas used
Also, by using this method, we account for all of the differences in gas caused by including the additional functionality, which isnāt actually the case when using the method I mentioned before.
Results:
WITHOUT additional code to find and delete the address from the array
Gas used to deploy contract:ā312,020
Gas used to run deletePerson: 44,292
WITH additional code to find and delete the address from the array
Gas used to deploy contract:ā341,771
Gas used to run deletePerson: 62,199
ADDITIONAL gas usedā¦
⦠to deploy contract: ā 29,751
⦠to run deletePerson: 17,907
Make of that what you will. As I said before it all comes down to a cost v benefit analysis really.
I would encourage you try to recreate the test Iāve explained above, not for the purposes of obtaining accurate results, but more for finding your way around and experimenting with the different information/data available in Remix in terms of the transaction reports and Debugger.
so we added an array to track creator addresses but if we delete some one should we not remove the address from the array?
not sure how you remove an item (you have to shift everything after the deleted location down one?
why can you iterate of a map (it can be done in Java, and JavaScript) is there a āblockchainā reason why we cant do this?