Access control helps decide who can do what in a smart contract. OpenZeppelin makes it easy to add these rules safely.
Access control with OpenZeppelin in Blockchain / Solidity
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
Blockchain / Solidity
import "@openzeppelin/contracts/access/AccessControl.sol"; contract MyContract is AccessControl { bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); constructor() { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(ADMIN_ROLE, msg.sender); } function restrictedFunction() public onlyRole(ADMIN_ROLE) { // code only admins can run } }
Use onlyRole(role) modifier to restrict function access.
Roles are identified by bytes32 hashes, usually created with keccak256.
Examples
MINTER_ROLE and restricts the mint function to users with that role.Blockchain / Solidity
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
function mint() public onlyRole(MINTER_ROLE) {
// mint tokens
}Blockchain / Solidity
constructor() {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}ADMIN_ROLE to others.Blockchain / Solidity
function grantAdmin(address user) public onlyRole(DEFAULT_ADMIN_ROLE) {
grantRole(ADMIN_ROLE, user);
}Sample Program
This contract lets only users with the EDITOR_ROLE change the data. The deployer starts with admin and editor roles.
Blockchain / Solidity
pragma solidity ^0.8.20; import "@openzeppelin/contracts/access/AccessControl.sol"; contract SimpleAccess is AccessControl { bytes32 public constant EDITOR_ROLE = keccak256("EDITOR_ROLE"); string public data; constructor() { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(EDITOR_ROLE, msg.sender); } function setData(string memory newData) public onlyRole(EDITOR_ROLE) { data = newData; } function getData() public view returns (string memory) { return data; } }
Important Notes
Remember to assign roles carefully to avoid locking out important functions.
OpenZeppelin's AccessControl is safer and easier than writing your own permission checks.
Use DEFAULT_ADMIN_ROLE to manage other roles.
Summary
Access control restricts who can use certain functions in a contract.
OpenZeppelin provides ready-made tools to add roles and permissions.
Use onlyRole modifier to protect functions easily.
Practice
1. What is the main purpose of using
onlyRole modifier in OpenZeppelin's Access Control?easy
Solution
Step 1: Understand the purpose of
TheonlyRoleonlyRolemodifier is used to limit access to functions so only users with a certain role can execute them.Step 2: Analyze the options
To restrict function access to accounts with a specific role correctly states that it restricts function access to accounts with a specific role. Other options describe unrelated behaviors.Final Answer:
To restrict function access to accounts with a specific role -> Option AQuick Check:
Access control = restrict by role [OK]
Hint: Remember: onlyRole means only users with that role can call [OK]
Common Mistakes:
- Thinking onlyRole assigns roles automatically
- Believing onlyRole allows open access
- Confusing onlyRole with event logging
2. Which of the following is the correct way to declare a role constant in OpenZeppelin Access Control?
easy
Solution
Step 1: Recall role declaration syntax
OpenZeppelin usesbytes32constants withkeccak256hash of a string to define roles.Step 2: Check each option
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); matches the correct pattern. Options B, C, and D use wrong types or formats.Final Answer:
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); -> Option DQuick Check:
Role constants use bytes32 + keccak256 [OK]
Hint: Roles are bytes32 constants hashed with keccak256 [OK]
Common Mistakes:
- Using string instead of bytes32 for roles
- Assigning numeric or address types to roles
- Forgetting to use keccak256 hash
3. Given the following Solidity code snippet, what will happen if an account without the ADMIN_ROLE calls
secureFunction()?
contract MyContract is AccessControl {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
constructor() {
_grantRole(ADMIN_ROLE, msg.sender);
}
function secureFunction() public onlyRole(ADMIN_ROLE) {
// critical logic
}
}medium
Solution
Step 1: Understand the
TheonlyRolemodifier behavioronlyRole(ADMIN_ROLE)modifier restricts access to accounts with ADMIN_ROLE. If the caller lacks this role, the call reverts.Step 2: Analyze the scenario
The constructor grants ADMIN_ROLE only tomsg.senderat deployment. Any other account callingsecureFunctionwill trigger a revert due to missing role.Final Answer:
The call reverts with an access control error -> Option BQuick Check:
Missing role causes revert [OK]
Hint: Only accounts with role can call; others revert [OK]
Common Mistakes:
- Assuming function runs without role
- Thinking warnings are emitted instead of revert
- Confusing role with ownership
4. Identify the error in this OpenZeppelin Access Control code snippet:
contract MyContract is AccessControl {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
constructor() {
_grantRole(ADMIN_ROLE, msg.sender);
}
function restricted() public onlyRole(ADMIN_ROLE) {
// restricted logic
}
function grantAdmin(address user) public {
_grantRole(ADMIN_ROLE, user);
}
}medium
Solution
Step 1: Review access control on
ThegrantAdmingrantAdminfunction calls_grantRolebut has no modifier restricting who can call it.Step 2: Identify security risk
Without access control, anyone can callgrantAdminand assign ADMIN_ROLE to themselves or others, breaking security.Final Answer:
ThegrantAdminfunction lacks access control and can be called by anyone -> Option AQuick Check:
Grant functions need access control [OK]
Hint: Always protect grantRole functions with onlyRole [OK]
Common Mistakes:
- Ignoring missing access control on grant functions
- Thinking _grantRole is protected like grantRole
- Confusing role declaration syntax
5. You want to create a smart contract where only users with the MINTER_ROLE can mint tokens, and only the contract owner can assign the MINTER_ROLE. Which OpenZeppelin pattern correctly enforces this?
hard
Solution
Step 1: Understand role assignment control
To restrict who can assign MINTER_ROLE, use AccessControl's DEFAULT_ADMIN_ROLE for admin rights and protect assignment functions withonlyRole(DEFAULT_ADMIN_ROLE).Step 2: Connect owner with DEFAULT_ADMIN_ROLE
Grant DEFAULT_ADMIN_ROLE to the contract owner so only they can assign MINTER_ROLE to others.Final Answer:
Use AccessControl with MINTER_ROLE and add onlyRole(DEFAULT_ADMIN_ROLE) modifier to the role assignment function, granting DEFAULT_ADMIN_ROLE to the owner -> Option CQuick Check:
Admin role controls role assignment [OK]
Hint: Use DEFAULT_ADMIN_ROLE for owner to control role assignments [OK]
Common Mistakes:
- Allowing anyone to assign roles
- Using Ownable without roles for minting
- Assigning roles to everyone by default
