Modifiers

Reusable pre- and post-conditions that wrap your functions. The building block of access control.

What is a modifier?

A modifier is a piece of code that runs before (or after) a function executes. They're used to enforce preconditions — checks that must pass before the function body runs. The _; placeholder marks where the function body is inserted.

solidity
modifier onlyOwner() {
    require(msg.sender == owner, 'Not the owner');
    _;  // the function body runs here
}

function setFee(uint256 newFee) external onlyOwner {
    fee = newFee;
    // onlyOwner check runs first — if msg.sender != owner, it reverts before reaching here
}

Parameterized modifiers

Modifiers can accept parameters, making them flexible enough to handle varying conditions.

solidity
modifier minimumAmount(uint256 min) {
    require(msg.value >= min, 'Insufficient ETH sent');
    _;
}

function premiumMint() external payable minimumAmount(0.1 ether) {
    _mint(msg.sender, 1);
}

Multiple modifiers

Functions can have multiple modifiers. They execute left to right, each waiting for the previous one to place its _;.

solidity
modifier onlyOwner() {
    require(msg.sender == owner, 'Not owner');
    _;
}

modifier whenNotPaused() {
    require(!paused, 'Contract is paused');
    _;
}

function withdraw(uint256 amount) external onlyOwner whenNotPaused {
    // Runs: onlyOwner check → whenNotPaused check → function body
    payable(msg.sender).transfer(amount);
}

Post-condition modifiers

Code after _; runs after the function body. This is less common but useful for invariant checks.

solidity
modifier checkInvariant() {
    _;
    // Runs after the function body
    assert(totalSupply == _sumOfBalances());
}

function mint(address to, uint256 amount) internal checkInvariant {
    balances[to] += amount;
    totalSupply += amount;
}

Common modifier patterns

  • onlyOwner — Restrict to contract owner
  • whenNotPaused / whenPaused — Emergency circuit breaker
  • nonReentrant — Prevent reentrancy attacks (OpenZeppelin's most-used modifier)
  • onlyRole(role) — Role-based access control

Rather than reinventing these, prefer OpenZeppelin's battle-tested implementations:

solidity
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/utils/ReentrancyGuard.sol';

contract MyContract is Ownable, ReentrancyGuard {
    function sensitiveAction() external onlyOwner nonReentrant {
        // ...
    }
}
←   Events and loggingInheritance and abstract contracts   →