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)