Functions & calls

Access control (modifiers)

Rust has no modifier keyword. You write a small guard method and call it at the top of each protected method — same effect, plain code.

Solidity’s modifier onlyOwner wraps a function with a reusable check. Rust has no modifiers, and that is fine: you write a private guard method and call it as the first line of each protected method.

Owner-only setter
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract Config {
    address public owner;
    uint32 public value;

    constructor() { owner = msg.sender; }

    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }

    function setValue(uint32 v) external onlyOwner {
        value = v;
    }
}
Rust
use near_sdk::{near, env, require, AccountId};

#[near(contract_state)]
pub struct Config {
    owner: AccountId,
    value: u32,
}

#[near]
impl Config {
    #[init]
    pub fn new() -> Self {
        Self { owner: env::predecessor_account_id(), value: 0 }
    }

    pub fn set_value(&mut self, v: u32) {
        self.assert_owner();
        self.value = v;
    }
}

// a plain private helper — not exposed as a contract method
impl Config {
    fn assert_owner(&self) {
        require!(env::predecessor_account_id() == self.owner, "not owner");
    }
}
Coming from EVM

modifier onlyOwner { ...; _; } + onlyOwner ↔ a private assert_owner(&self) called at the top of the method. No macro magic needed — it is just a function call.

Put helpers in a separate `impl` block without `#[near]` (or a non-pub fn) so they stay internal and are never exposed as callable contract methods.

For role-based access across many methods, keep a LookupMap<AccountId, Role> and a guard like assert_role(Role::Admin) — the same pattern, scaled up.