NEWTON
Asked
3 months ago
89
views
0
How to use Access Control in Cairo securely? What library can I use for implementing it?
Newton
asked
3 months ago
1
Accepted answer
The first rule in access control is the principle of least privilege
which states that users should have the minimum necessary privileges required to do their job.
This can often be difficult to implement in smart contracts, as it would require managing many different accounts, therefore it is common to see the privileged functions of a smart contract being protected by at least an owner
role, which ideally is secured by a multi-signature wallet.
With Cairo, we have two main libraries which can be used to implement access control (both provided to us by OpenZeppelin):
It is important to ensure that the roles implemented fit the purpose of the protocol, and have the least possible amount of privileges. Furthermore, use of multi-signature wallets where appropriate is highly encouraged.
For instance, if we were to implement a custom ERC20 contract, we could implement the following roles:
Owner
or Admin
- Owns the contract and can transfer ownership/assign roles to others as well as perform other management activityMinter
- Can mint new tokensPauser
- Can pause the contractUpgrader
- Can upgrade the contract (in case of an upgradeable contract)As mentioned above, we have two options for this, either use Ownable
or AccessControl
. For impementing more roles, it makes more sense to use AccessControl
, as otherwise we would have to make amendment to the Ownable
library, which is not recommended.
With AccessControl
, we can set arbitrary roles, and have them verified in a similar fashion. In this case, we will set the admin role in the constructor of our contract, just after initializing the library. Now that we have an admin role, we can use it to set all other roles. Let's try and implement a minter
role:
@external func grantRole{ syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr }(role: felt, user: felt) { AccessControl.grant_role(role, user); return (); }
And then protect our mint
function to only allow the minter
to call it, using a modifier which looks like the one below:
func assert_only_role{ syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr }(role: felt) { alloc_locals let (caller) = get_caller_address(); let (authorized) = has_role(role, caller); with_attr error_message("AccessControl: caller is missing role {role}") { assert authorized = TRUE; } return (); }
And this is our code with the new added check:
@external func mint{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr }(to: felt, amount: Uint256) { let (caller) = get_caller_address(); AccessControl.assert_only_role(120299592115570, caller); ERC20._mint(to, amount); return (); }
And this should fail if the caller does not have the minter role.
ctrlc03
answered
3 months ago
What libraries are secure to use in Cairo?
Why will I use events in Cairo language?
Cairo: When do you use tempvar and when do you use local
Cairo: Getting the zero address
How to use `await` in StarkNet.py?
How can I use meta-class of contract (starknetjs) for interaction?
What are events in Cairo Language?
Hey, is there anyway to debug Cairo contracts in hardhat environment? Something like hardhat console in solidity
What libraries are secure to use in Cairo?
What is the maximum value an uint and felt can store in Cairo Language?
Cairo Lang / StarkNet: What are Revoked references? What is alloc_locals?
Cairo Owner Only Fuctions
How can I use dynamic allocation in Cairo?
Is there a cheatsheet somewhere will all the most usefull commands