OpenZeppelin Access Control is a Solidity library that provides a robust framework for managing permissions in smart contracts. It allows developers to define roles, assign them to addresses, and enforce access restrictions on functions based on these roles.
How to implement access controls and permissions in Solidity
Key takeaways:
Access controls and permissions in Solidity are critical for regulating access to functions within a smart contract.
They ensure that only authorized users can perform specific operations, enhancing the security and integrity of the contract and preventing unauthorized access or manipulation.
One effective approach to implementing access controls is Role-Based Access Control (RBAC). This involves defining state variables (such as
contractOwner,admins, andusers), creating a constructor to initialize these variables, and using modifiers likeonlyContractOwner,onlyAdmin, andonlyUserto enforce access restrictions. The modifiers utilizerequirestatements to validate the caller's identity before executing functions.Implementing robust access controls in Solidity is essential for building secure decentralized applications.
Access controls and permissions in Solidity are techniques that regulate access to functions within a smart contract. They ensure that only authorized entities can perform certain operations. Solidity performs it using modifier and require statements, which enforce access restrictions and validate conditions before executing functions.
Implementing access controls and permissions enhances the security and integrity of smart contracts by preventing unauthorized access and manipulation.
Implementation
There’re various methods to implement access controls and permissions in Solidity. One of those techniques is using Role-Based Access Control (RBAC). Let’s look at the following steps to get a better idea of its implementation:
Define contract
Define the contract and declare the required state variables initially. We are using solidity version 0.5.12 here.
pragma solidity ^0.5.12;contract AccessControl {address public contractOwner;mapping(address => bool) public admins;mapping(address => bool) public users;}
- Line 1: Add the version
pragmain Solidity. It specifies the version of the Solidity compiler that should be used to compile the contract code. - Line 3–7: Define the contract and declare the state variables
contractOwner,admins, andusersto keep track of the contract owner, admin addresses, and user addresses, respectively.
Create constructor
Now create the constructor to initialize the contract owner and default admin:
constructor() {contractOwner = msg.sender;admins[msg.sender] = true;}
- Line 1–4: Assign the contract’s address to the
contractOwnervariable and mark the deployer as a default admin by settingadmins[msg.sender]to true.
Create modifiers
Once the contract owner and default admin have been initialized, it’s time to set up the modifiers for role-based access control.
// Modifier for contract ownermodifier onlyContractOwner() {require(msg.sender == contractOwner, "Only contract owner is allowed to call this function");_;}// Modifier for adminmodifier onlyAdmin() {require(admins[msg.sender], "Only admin is allowed to call this function");_;}// Modifier for usermodifier onlyUser() {require(users[msg.sender], "Only registered users are allowed to call this function");_;}
- Line 2–3: The
onlyContractOwnerfunction verifies that the contract owner is the caller of a function. It uses arequirestatement to verify the condition; if it fails, it throws an error message. - Line 4: Represents the location where the modified function’s body will be executed.
- Line 8–11: The
onlyAdminfunction verifies that the admin is the caller of a function. It checks if the caller’s address exists in theadminsmapping, and if not, it throws an error. - Line 14–17: The
onlyUserfunction verifies that the registered user is the caller of a function. It checks if the caller’s address exists in theusersmapping; if not, it throws an error.
Implement functionalities for access control
Now let’s create functions to add or remove admins and register or stop user access. These functions can only be called by the contract owner or admins, respectively.
// Add an adminfunction addAdmin(address admin) public onlyContractOwner {admins[admin] = true;}// Remove an adminfunction removeAdmin(address admin) public onlyContractOwner {admins[admin] = false;}// Register a userfunction registerUser(address user) public onlyAdmin {users[user] = true;}// Stop the access of a userfunction stopUser(address user) public onlyAdmin {users[user] = false;}
- Line 2–9: These functions only allow the contract owner to add and remove an admin. It takes an
adminaddress as a parameter and sets the correspondingadmins[admin]mapping value totrueandfalse. - Line 12–19: These functions only allow the admin to register and stop a user’s access. It takes a
useraddress as a parameter and sets the correspondingusers[user]mapping value totrueandfalse.
pragma solidity ^0.5.12;
contract AccessControl {
address public contractOwner;
mapping(address => bool) public admins;
mapping(address => bool) public users;
constructor() {
contractOwner = msg.sender;
admins[msg.sender] = true;
}
// Modifier for contract owner
modifier onlyContractOwner() {
require(msg.sender == contractOwner, "Only contract owner is allowed to call this function");
_;
}
// Modifier for admin
modifier onlyAdmin() {
require(admins[msg.sender], "Only admin is allowed to call this function");
_;
}
// Modifier for user
modifier onlyUser() {
require(users[msg.sender], "Only registered users are allowed to call this function");
_;
}
// Add an admin
function addAdmin(address admin) public onlyContractOwner {
admins[admin] = true;
}
// Remove an admin
function removeAdmin(address admin) public onlyContractOwner {
admins[admin] = false;
}
// Register a user
function registerUser(address user) public onlyAdmin {
users[user] = true;
}
// Stop the access of a user
function stopUser(address user) public onlyAdmin {
users[user] = false;
}
}Conclusion
In conclusion, implementing access controls and permissions in Solidity is essential for maintaining the security and integrity of smart contracts. By using techniques such as Role-Based Access Control (RBAC) and incorporating modifiers like onlyAdmin or onlyContractOwner, developers can ensure that only authorized entities can access or modify contract functions. These access controls help prevent unauthorized manipulation and safeguard the contract’s intended functionality. Whether managing admin privileges or user access, proper implementation of these techniques plays a critical role in building secure, trustworthy decentralized applications.
Frequently asked questions
Haven’t found what you were looking for? Contact Us
What is OpenZeppelin access control?
What is access control in Solidity?
What is an access control list (ACL)?
Free Resources