Lesson 10 of 25
Modifiers
Create reusable access control and validation logic with function modifiers.
IntermediateWhat Are Modifiers?
Modifiers wrap function calls with pre-conditions (and post-conditions). They are the idiomatic Solidity way to implement access control, reentrancy guards, and input validation without repeating code.
The
_; placeholder marks where the function body executes.
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ModifierDemo {
address public owner;
constructor() {
owner = msg.sender;
}
// Modifier definition
modifier onlyOwner() {
require(msg.sender == owner, "Not the owner");
_; // function body executes here
}
// Apply modifier to a function
function sensitiveAction() public onlyOwner {
// Only the owner can reach this code
}
}
Modifier with Parameters
Modifiers can accept parameters, making them more flexible.
Solidity
contract Parametric {
mapping(address => uint256) public balances;
modifier hasBalance(uint256 amount) {
require(balances[msg.sender] >= amount, "Insufficient funds");
_;
}
modifier validAddress(address addr) {
require(addr != address(0), "Zero address");
_;
}
function withdraw(uint256 amount) public hasBalance(amount) {
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
function send(address to, uint256 amount)
public
hasBalance(amount)
validAddress(to)
{
balances[msg.sender] -= amount;
balances[to] += amount;
}
}
Chaining Modifiers
Multiple modifiers can be applied to one function. They execute left-to-right.
Solidity
contract Chained {
address public owner;
bool public paused;
constructor() { owner = msg.sender; }
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
modifier notPaused() {
require(!paused, "Contract is paused");
_;
}
function setPaused(bool _p) public onlyOwner {
paused = _p;
}
// Both modifiers run before the function body
function criticalAction() public onlyOwner notPaused {
// safe to execute
}
}
Post-Condition Modifiers
Code after
_; runs AFTER the function body — useful for post-condition checks.
Solidity
contract PostCondition {
uint256 public balance = 1000;
// Ensures balance never goes negative
modifier balanceCheck() {
_; // function runs first
require(balance <= 10000, "Balance cap exceeded");
}
function deposit(uint256 amount) public balanceCheck {
balance += amount;
// modifier check runs after this line
}
}