How to Add Permissions to Your Smart Contract in Solidity
In this guide, we will show how to add permissions to a smart contract to manage access control.
We will use the thirdweb CLI to create an NFT smart contract, add the thirdweb permissions extension and then implement access control in our contract. Finally, we will deploy the contract and grant a new role to a user.
Let's get started!
Create A Solidity Project
In your terminal, create a new contract with this command:
npx thirdweb@latest create contract
- Give your project a name.
- Select the development framework (we will use Hardhat in this guide).
- Choose the contract you’d like to start with (we are starting from an
Empty Contract
).
Once the project has been built, open it up in your favorite IDE and start building.
This installs the @thirdweb-dev/contracts
package into a new Solidity project; which we'll use to import permissions.
Add Permissions To Your Smart Contract
To add permissions, we need to import the thirdweb permissions contract. In contracts/Contract.sol
import the thirdweb permissions contract and make your contract inherit it.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
import "@thirdweb-dev/contracts/extension/Permissions.sol";
contract MyContract is Permissions {
constructor() {}
}
The thirdweb permissions contract comes with a pre-defined role - the DEFAULT_ADMIN_ROLE
. We can start by assigning that role to the deployer of the contract in the constructor:
constructor() {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
To enforce access control, we can use the onlyRole
modifier provided by the Permissions.sol
contract to check for a specific role.
Let's create a new function; add
, and require that only people with the DEFAULT_ADMIN_ROLE
can invoke the function.
function add(uint256 a, uint256 b) public view onlyRole(DEFAULT_ADMIN_ROLE) returns (uint256) {
return a + b;
}
Create A Role For Permission Controls
Roles can be any bytes32
value so you can define a new role (at the top of your contract) like this:
bytes32 public constant SUBTRACT_ROLE = keccak256("SUBTRACT_ROLE");
Let's add some functionality to the contract and use the new role. Start by creating a new variable called number
:
uint256 public number;
Then, change the add
function so that it adds the provided number to the number
variable instead of simply adding two numbers.
function add(uint256 a) public onlyRole(DEFAULT_ADMIN_ROLE){
number += a;
}
Now, create a new function called subtract
which subtracts a provided number from the number
variable and can only be called by those who hold the SUBTRACT_ROLE
.
Your full contract should look like this:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
import "@thirdweb-dev/contracts/extension/Permissions.sol";
contract MyContract is Permissions {
bytes32 public constant SUBTRACT_ROLE = keccak256("SUBTRACT_ROLE");
uint256 public number;
constructor() {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function add(uint256 a) public onlyRole(DEFAULT_ADMIN_ROLE) {
number += a;
}
function subtract(uint256 a) public onlyRole(SUBTRACT_ROLE) {
number -= a;
}
}
Assign A Role To A Wallet Address
The grantRole
function (inherited from the Permissions
contract) can be used to assign a role to a wallet address.
The easiest way to do this is to deploy your contract with the CLI, and then invoke the grantRole
function from the dashboard.
To deploy your contract, run the following command from your smart contract project directory:
npx thirdweb@latest deploy
Once the contract is deployed, you'll find yourself in the contract dashboard. Take a few minutes to explore the dashboard.
- Check out the
Explorer
tab, which allows you to interact with your deployed contract - View events from your contract in the
Events
tab - Imagine what you can build with the code snippets in the
Code
tab.
To assign a role, go to the Explorer
tab in the dashboard. From the WRITE
functions, select the grantRole
function.
Notice that we have to provide the role
(as a bytes32
) and the account
(wallet address). The role we want to grant is the SUBTRACT_ROLE
which we defined earlier with this line of code.
bytes32 public constant SUBTRACT_ROLE = keccak256("SUBTRACT_ROLE");
To get this bytes32
value, we can use an online tool like this one, and convert "SUBTRACT_ROLE" to a bytes32
value. Your bytes32
value should look like this: 0x3ccb835e934d10e2ec13cf39065b900d8b3d4a3a39038f8b762590a977809e5e
.
You can paste your bytes32
value into the dashboard, add the wallet address to which you want to assign the role, and then click on the Execute
button and approve the transaction.
You can see the output from the transaction in the dashboard, and you can view the emitted event in the Events
tab.
Conclusion
Awesome 🎉 You have added permissions to your contract, created a new role, and granted that role to a wallet.
For any questions you have, please join the thirdweb discord! It is a great place to find fellow builders and ask any questions you may have. The whole thirdweb team is there waiting for you!