Access control patterns help decide who can do what in a blockchain system. They keep things safe by letting only the right people make changes.
Access control patterns in Blockchain / Solidity
contract AccessControl {
mapping(address => bool) private admins;
modifier onlyAdmin() {
require(admins[msg.sender], "Not an admin");
_;
}
function addAdmin(address user) public onlyAdmin {
admins[user] = true;
}
function removeAdmin(address user) public onlyAdmin {
admins[user] = false;
}
function restrictedAction() public onlyAdmin {
// action only admins can do
}
}modifier is a way to check permissions before running a function.
mapping(address => bool) stores which addresses have access.
mapping(address => bool) private whitelist; function addToWhitelist(address user) public { whitelist[user] = true; } function checkAccess() public view returns (bool) { return whitelist[msg.sender]; }
enum Role { None, User, Admin }
mapping(address => Role) roles;
function setRole(address user, Role role) public {
roles[user] = role;
}
modifier onlyAdmin() {
require(roles[msg.sender] == Role.Admin, "Not admin");
_;
}This smart contract lets the creator be the first admin. Admins can add or remove other admins. Only admins can call these functions.
pragma solidity ^0.8.0; contract SimpleAccessControl { mapping(address => bool) private admins; constructor() { admins[msg.sender] = true; // creator is admin } modifier onlyAdmin() { require(admins[msg.sender], "Not an admin"); _; } function addAdmin(address user) public onlyAdmin { admins[user] = true; } function removeAdmin(address user) public onlyAdmin { admins[user] = false; } function isAdmin(address user) public view returns (bool) { return admins[user]; } }
Always test access control carefully to avoid security holes.
Use modifiers to keep your code clean and avoid repeating permission checks.
Remember that blockchain data is public, so access control protects actions, not data visibility.
Access control patterns decide who can use blockchain functions.
Use mappings or enums to track permissions.
Modifiers help check permissions before running code.
Practice
Solution
Step 1: Understand access control concept
Access control limits permissions, deciding who can do what on the blockchain.Step 2: Identify the main goal
The goal is to protect blockchain data and functions by restricting unauthorized actions.Final Answer:
To restrict who can perform certain actions on the blockchain -> Option AQuick Check:
Access control = restrict actions [OK]
- Confusing access control with transaction speed
- Thinking access control stores data
- Assuming access control creates cryptocurrencies
onlyOwner for access control?Solution
Step 1: Recall modifier syntax in Solidity
A modifier uses the keyword 'modifier', parentheses for parameters, and the '_;' placeholder.Step 2: Check each option
modifier onlyOwner() { require(msg.sender == owner); _; } correctly uses 'modifier onlyOwner() { require(msg.sender == owner); _; }'. Others have syntax errors or missing parts.Final Answer:
modifier onlyOwner() { require(msg.sender == owner); _; } -> Option DQuick Check:
Modifier syntax = modifier onlyOwner() { require(msg.sender == owner); _; } [OK]
- Using 'function' instead of 'modifier'
- Omitting parentheses after modifier name
- Using arrow syntax which is invalid here
mapping(address => bool) public admins;
modifier onlyAdmin() {
require(admins[msg.sender], "Not admin");
_;
}
function addAdmin(address newAdmin) public onlyAdmin {
admins[newAdmin] = true;
}
constructor() {
admins[msg.sender] = true;
}
What happens if a non-admin calls addAdmin?Solution
Step 1: Understand the onlyAdmin modifier
The modifier requires that the caller's address is in the admins mapping as true, else it reverts with "Not admin".Step 2: Analyze calling addAdmin by non-admin
If the caller is not an admin, require fails, causing the transaction to revert with the error message.Final Answer:
The transaction reverts with error 'Not admin' -> Option BQuick Check:
Non-admin call triggers require revert [OK]
- Assuming function silently fails
- Thinking non-admin can add admins
- Believing contract crashes permanently
address public owner;
modifier onlyOwner() {
require(msg.sender = owner, "Not owner");
_;
}
constructor() {
owner = msg.sender;
}
Solution
Step 1: Check require statement syntax
The require uses '=' which assigns, not '==' which compares. This causes a compile error or unexpected behavior.Step 2: Verify other parts
Semicolon is present, constructor name is correct, and modifier has parentheses, so no issues there.Final Answer:
Using assignment '=' instead of comparison '==' in require -> Option CQuick Check:
Use '==' for comparison in require [OK]
- Confusing '=' and '==' in conditions
- Thinking constructor name must differ
- Ignoring parentheses in modifier
Solution
Step 1: Understand multi-level access control needs
Different roles require different permissions; owner controls admins, admins control users, users have limited access.Step 2: Evaluate patterns
Nested mappings with modifiers (Use nested mappings with modifiers for owner, admin, and user roles) is complex but correct. Single boolean mapping (Use a single boolean mapping for all roles and check in functions) cannot distinguish roles well. Public variables without modifiers (Use public variables for roles without modifiers) is insecure and insufficient. Events only (Use events only to track roles without restrictions) do not enforce control.Step 3: Choose best practical pattern
Nested mappings with modifiers provide clear, secure role checks and control flow.Final Answer:
Use nested mappings with modifiers for owner, admin, and user roles -> Option AQuick Check:
Multi-level roles need nested mappings + modifiers [OK]
- Using single mapping for all roles
- Skipping modifiers for access checks
- Relying only on events without restrictions
Ready to prove it?
Pass the test and this pattern moves unknown
