@pedromndias @filip … @anyoneelse
While I’m on a roll, here are the other questions I have about this section on Error Handling:
Question 1
Quiz question: When should you use assert()
?
Answer: To avoid conditions which should never, ever be possible.
I put to avoid compilation errors, because assert()
can throw if there is an error in our code which does not comply with an invariant. However, is my answer wrong, because compilation errors refer to syntax and so won’t actually trigger assert()
, which is instead only triggered by coding errors which would result in an output which should be impossible (i.e. one that fails to meet an invariant condition)?
Question 2
In our createPerson
function…
people[msg.sender]
should always be equal to newPerson
(this is our invariant)
… so I understand why we need to combine the properties of each of these into single hex values with abi.encodePacked()
in order to be able to compare them.
But why does Solidity further require us to hash these hex values? Surely, if the unhashed hex values equal each other, this is enough to prove that our invariant condition has been met?
Question 3
In the deletePerson
function we have the following assert
function
assert(people[creator].age == 0);
I extended this as follows, and as expected it also works:
assert(
people[creator].age == 0 &&
people[creator].height == 0 &&
people[creator].senior == false
);
However, why can’t we also use the following, and how could we get it to work?
assert(people[creator].name == "");
Also, if we have deleted the person from our mapping, why do we still have a struct which contains the properties: age 0, height 0, senior false? Surely, if the person has been deleted, an assert
function with the above conditions for invariants should still fail, because the properties age, height and senior shouldn’t even exist? Instead, it seems like we still have a person, but one with no name, height 0, age 0 (and not a senior).
This anomoly is also evident when getPerson
is called for the same account which has just had its person deleted — it returns a person with no name, age 0, height 0, and senior false
.
This seems strange to me — what’s actually happening here?
Question 4
Following on from Question 3, if the whole Person
struct isn’t actually deleted, but its properties just effectively set to falsy values, could we improve the getPerson
function by including a require
function that throws and cancels execution if either:
(i) no person has been created for that address yet; or
(ii) the person created has since been deleted?
It would make sense to me that in these circumstances we should receive an error message such as “You must create a person before you can get it”, rather than getPerson
returning a person with no name, age 0, height 0, and senior false
, as it does at the moment.
In an attempt to create something along these lines, I’ve added the following to the getPerson
function body:
require(
people[msg.sender].height != 0,
"You must create a person before you can get it"
);
This works, but it’s hardly ideal. Can we not ensure that the whole Person
struct is deleted from the mapping, and then have a require
function with the condition that a Person
struct exists for this address (no matter what property values it contains), and failing if it doesn’t?