1. Modifiers Can Change State
- Usual role: run
require
checks before function execution. - Hidden power: modifiers can update state variables.
address public owner;
uint public modifierCount;
modifier onlyOwner {
require(msg.sender == owner);
modifierCount++; // state change inside modifier
_;
}
Result: modifierCount increases every time onlyOwner is triggered.
Takeaway: modifiers can serve as pre-processors (logging, state prep, counters).
2. Evolution: Dynamic Modifiers With Parameters
(a) Literal Parameters
Instead of writing many modifiers, pass values directly:
modifier cost(uint value) {
require(msg.value >= value, "Insufficient fee");
_;
}
function setX() public payable cost(1 ether) { ... }
function setY() public payable cost(2 ether) { ... }
Flexible: one generic modifier → multiple use cases.
(b) Function Parameters
Modifiers can also take function arguments:
modifier greaterThan(uint val, uint min) {
require(val > min, "Input value is too low");
_;
}
function setX(uint num) public greaterThan(num, 10) {
// executes only if num > 10
}
3. Execution Order of Multiple Modifiers
Multiple modifiers run in the listed order.
function setX(uint num)
public
payable
cost(1 ether)
greaterThan(num, 10)
{
// ...
}
Flow:
- cost runs first.
- Then greaterThan.
- Only then the function body.
Mechanism: each _ means “execute the next step in the chain”.
Function body is just the last step in the chain.
4. Multiple _ → Multiple Executions
You can place multiple _ in one modifier.
uint public count;
modifier tripleExecute(uint val) {
require(val > 10, "Too low");
_;
_;
_;
}
function setX(uint num) public tripleExecute(num) {
count++;
}
setX increments count three times per call.
Rarely practical, but illustrates that _ = “insert function body here.
Conclusion
Modifiers can:
Update state directly.
Accept dynamic parameters (literals + function inputs).
Chain together in controlled execution order.
Execute functions multiple times with multiple _.
Top comments (0)