- Write modifiers with and without arguments.
- Explain the role and position of the
_;placeholder (merge wildcard). - Apply several modifiers to one function and predict their order.
- Use common modifier patterns such as onlyOwner, state checks and a reentrancy guard.
Solidity Modifiers
- A function modifier is reusable code that changes the behaviour of a function – most often it checks a condition before the function runs.
- If the condition is not met, the modifier reverts and the function body is not executed.
- Modifiers can also run code after the function body, and they keep repeated checks (such as “only the owner may call this”) in one place.
- All course projects use modifiers, e.g.
checkBlockAdmin()andcheckVoterCasting()in the Election System.
Two Variations of a Function Modifier
1. Function modifier without arguments:
modifier modifierName() {
// checks / action to be taken
_;
}
2. Function modifier with arguments:
modifier modifierName(uint arg) {
// checks using arg
_;
}
Apply a modifier by writing its name in the function header: function withdraw() public onlyOwner { ... }. Parentheses are optional when there are no arguments.
What is the Merge Wildcard ( _; )?
- The
_;symbol is called the placeholder or merge wildcard. During compilation it is replaced by the body of the function the modifier is applied to. - Control moves to the function body at the point where
_;appears. - Code placed before
_;runs before the function (the usual place for checks); code placed after_;runs after the function body. - Without
_;the function body would never run, so every modifier that should let the function execute must contain it. It may appear more than once (the body then runs more than once), which is rarely useful. - A
returninside the function body leaves only the body; any modifier code after_;still executes.
Several Modifiers on One Function
Modifiers are applied in the order they are written. In function f() public onlyOwner whenOpen { ... }, onlyOwner runs first; its _; runs whenOpen, whose _; runs the body. Like functions, modifiers can be inherited and overridden using virtual/override.
Example : Common Modifier Patterns
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Ticketing {
address public owner;
bool public saleOpen = true;
uint public sold;
bool private locked;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() { // without arguments
require(msg.sender == owner, "Only owner");
_;
}
modifier whenOpen() {
require(saleOpen, "Sale closed");
_;
}
modifier costs(uint price) { // with an argument
require(msg.value == price, "Wrong amount");
_;
}
modifier nonReentrant() { // code before AND after _;
require(!locked, "No re-entry");
locked = true;
_;
locked = false;
}
function buy() external payable whenOpen costs(0.01 ether) {
sold += 1;
}
function closeSale() external onlyOwner {
saleOpen = false;
}
function withdraw() external onlyOwner nonReentrant {
(bool ok, ) = payable(owner).call{value: address(this).balance}("");
require(ok, "Transfer failed");
}
}
Key Takeaways
- Modifiers package reusable checks; if a check fails, the function body does not run.
_;marks where the function body is inserted – checks before, clean-up after.- Multiple modifiers run left to right; modifiers can take arguments.
The PDF E-Notes are the earlier printable version of this chapter. The notes on this page are the latest, revised version.
Question / Answer (15 questions)
_; symbol (also called the placeholder). It is replaced by the body of the function the modifier is applied to, marking where that body executes.modifier onlyOwner() { require(msg.sender == owner, "Only owner"); _; }, applied as function withdraw() public onlyOwner { ... }.modifier costs(uint price) { require(msg.value == price, "Wrong amount"); _; }, used as function buy() external payable costs(0.01 ether) { ... }.onlyOwner and onlyOwner() are accepted.MCQ Test : Check Your Understanding (5 questions)
Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.
Bibliography/References
The notes, questions and MCQs on this page are original explanations written for this course. The works listed below were consulted and are cited for attribution and further reading. Product names, logos and trademarks belong to their respective owners. Short quotations, where used, are marked and attributed.
- Solidity Team. (n.d.). Contracts (creating contracts, visibility and getters, function modifiers, constant and immutable, functions, events, custom errors, inheritance, abstract contracts, interfaces, libraries). Solidity Documentation. https://docs.soliditylang.org/en/latest/contracts.html
- Solidity Team. (n.d.). Security Considerations. Solidity Documentation. https://docs.soliditylang.org/en/latest/security-considerations.html
- OpenZeppelin. (n.d.). OpenZeppelin Contracts Documentation. https://docs.openzeppelin.com/contracts/
- GeeksforGeeks. (n.d.). Solidity – Function Modifiers. https://www.geeksforgeeks.org/solidity-function-modifiers/
- Modi, R. (2018). Solidity Programming Essentials: A beginner’s guide to build smart contracts for Ethereum and blockchain. Packt Publishing. ISBN 978-1-78883-138-3.