6- Security and access control with OpenBrush
Prerequisites
Cargo contract installed: https://polkaverse.com/9768/technical-guide-install-cargo-contract-37738
At least on the following node is ready :
- swanky node: https://github.com/AstarNetwork/swanky-node/releases
- substrate contract node: https://github.com/paritytech/substrate-contracts-node/releases
This tutorial uses Ubuntu 22.04, cargo 1.68, cargo contract 2.0 and swanky node
Create the project
You can use the command “cargo contract new” to create a new contract based on the template “flipper“.
cargo contract new security
Use OpenBrush
Add openbrush
in your Cargo.toml
and to the std
features
openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "3.1.1", default-features = false }
[features]
default = ["std"]
std = [
"ink_metadata/std",
"ink/std",
"scale/std",
"scale-info/std",
"openbrush/std"
]
Ownable
OpenBrush provides only_owner
rights for contract’s function
Step 1: Import default implementation
Add the feature ownable
in your Cargo.toml
openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "3.1.1", default-features = false, features = ["ownable"] }
After enabling the feature and importing the corresponding module, you need to embed the module data structure into your contract as a field and implement the openbrush::traits::Storage
trait for that field. In most cases, the data structure of each module is named Data
. If importing several modules, you can specify which data you want to use via namespaces like ownable::Data
.
Each contract that wants to reuse implementation should implement the openbrush::traits::Storage
with the corresponding data structure. The easiest way to implement that trait is via the derive macro by adding #[derive(Storage)]
and marking the corresponding fields with the #[storage_field]
attribute.
Now your contract has access to default implementation on the Rust level. It is on the Rust level so you can call methods only inside your contract (in the example, it is methods of Ownable
, and ownable::Internal
traits). If you want to make all methods of some trait public, you should explicitly implement the corresponding trait.
Note: The default implementation of traits requires the usage of the unstable feature min-specialization. You can enable it by adding #![feature(min_specialization)]
at the top of your root module(for more information check rust official documentation). It also means you have to compile with the option nightly
Step 2: Define constructor
Define the constructor and initialize the owner with the contract initiator.
Step 3: Customize your contract
Customize it by adding ownable logic. We will add a only_owner
function to SecuryContract
implemenation and add the only_owner
modifier, which will verify that the caller of the function is the owner.
Build the project
In the directory “security“, use the command “cargo +nightly contract build” to compile the project.
cargo +nightly contract build
Deploy the contract
You can deploy your contract in a local node or a swanky node or a testnet.
Here we will start a swanky node and use Contracts UI to interact with the contract.
Here the result when the contract’s owner calls the method onlyOwner
Here the result when a non contract’s owner calls the method onlyOwner. The error CallerIsNotOwner
is returned by the method.
And you can also use the transferOwnership
function to transfer the ownership of this contract or play with the following functions
Access Control
OpenBrush provides only_role
rights for contract’s function
Step 1: Import default implementation
Add the feature access_control
in your Cargo.toml
openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "3.1.1", default-features = false, features = ["ownable", "access_control"] }
After enabling the feature and importing the corresponding module, you need to embed the module data structure into your contract as a field.
Now your contract has access to default implementation on the Rust level. It is on the Rust level so you can call methods only inside your contract. If you want to make all methods of some trait public, you should explicitly implement the corresponding trait.
Step 2: Define constructor
You can initialize the admin role for the owner with the contract initiator and you can also grant default roles for for the owner.
Step 3: Customize your contract
Customize it by adding access control logic. We will add a only_role_1
and only_role_2
functions to SecuryContract
implemenation. We also add getter for displaying the value behind each role.
Build the project
In the directory “security“, use the command “cargo +nightly contract build” to compile the project.
cargo +nightly contract build
Deploy the contract
You can deploy your contract in a local node or a swanky node or a testnet.
Here we will start a swanky node and use Contracts UI to interact with the contract.
Here the result when the user is granted to call the method.
Here the result when the user is not granted to call the method. The error MissingRole
is returned by the method.
And you can use the grantRole/revokeRole
functions to grant/revoke a role to the address. You can also use the following functions:
Conclusion
Manage the access control is very important when deploying a smart contract in the blockchain. OpenBrush allows an easy way to provide rights for usage of specific smart contract functions.
Git repository
https://github.com/GuiGou12358/astar-tutorials/tree/main/tuto6
Source
https://learn.brushfam.io/docs/OpenBrush/smart-contracts/ownable
https://learn.brushfam.io/docs/OpenBrush/smart-contracts/access-control/
Crypto-enthusiast, Defi & NFT believer, Dotsam Fam Astar Tech Amb & Phala Amb Web2 builder gradually migrating to Web3
Tutorials to write Smart Contracts in Rust and Ink!
0 comments