We saw earlier what a function modifier is, and we wrote a basic function modifier. Now let's look at modifiers in depth.
Modifiers are inherited by child contracts, and child contracts can override them. Multiple modifiers can be applied to a function by specifying them in a whitespace-separated list and will be evaluated in order. You can also pass arguments to modifiers.
Inside the modifier, the next modifier body or function body, whichever comes next, is inserted where _; appears.
Let's take a look at a complex code example of function modifiers:
contract sample
{
int a = 90;
modifier myModifier1(int b) {
int c = b;
_;
c = a;
a = 8;
}
modifier myModifier2 {
int c = a;
_;
}
modifier myModifier3 {
a = 96;
return;
_;
a = 99;
}
modifier myModifier4 {
int c = a;
_;
}
function myFunction() myModifier1(a) myModifier2 myModifier3 returns (int d)
{
a = 1;
return a;
}
}
This is how myFunction() is executed:
int c = b;
int c = a;
a = 96;
return;
int c = a;
a = 1;
return a;
a = 99;
c = a;
a = 8;
Here, when you call the myFunction method, it will return 0. But after that, when you try to access the state variable a, you will get 8.
return in a modifier or function body immediately leaves the whole function and the return value is assigned to whatever variable it needs to be.
In the case of functions, the code after return is executed after the caller's code execution is finished. And in the case of modifiers, the code after _; in the previous modifier is executed after the caller's code execution is finished. In the earlier example, line numbers 5, 6, and 7 are never executed. After line number 4, the execution starts from line numbers 8 to 10.
return inside modifiers cannot have a value associated with it. It always returns 0 bits.