AccessControl API
This page provides the full AccessControl module API.
Roles are referred to by their Bytes<32>
identifier.
These should be exposed in the top-level contract and be unique.
The best way to achieve this is by using export sealed ledger
hash digests that are initialized in the top-level contract:
import CompactStandardLibrary;
import "./node_modules/@openzeppelin-compact/contracts/src/access/AccessControl"
prefix AccessControl_;
export sealed ledger MY_ROLE: Bytes<32>;
constructor() {
MY_ROLE = persistentHash<Bytes<32>>(pad(32, "MY_ROLE"));
}
To restrict access to a circuit, use assertOnlyRole:
circuit foo(): [] {
assertOnlyRole(MY_ROLE);
}
Roles can be granted and revoked dynamically via the grantRole and revokeRole circuits. Each role has an associated admin role, and only accounts that have a role’s admin role can call grantRole and revokeRole.
By default, the admin role for all roles is DEFAULT_ADMIN_ROLE
,
which means that only accounts with this role will be able to grant or revoke other roles.
More complex role relationships can be created by using _setRoleAdmin.
To set a custom DEFAULT_ADMIN_ROLE
,
implement the Initializable
module and set DEFAULT_ADMIN_ROLE
in the initialize()
circuit.
The DEFAULT_ADMIN_ROLE
is also its own admin: it has permission to grant and revoke this role.
Extra precautions should be taken to secure accounts that have been granted it.
For an overview of the module, read the Access Control guide.
Core
AccessControl
import "./node_modules/@openzeppelin-compact/contracts/src/access/AccessControl";
Ledger
_operatorRoles: Map<Bytes<32>, Map<Either<ZswapCoinPublicKey, ContractAddress>, Boolean>>
ledger
#Mapping from a role identifier -> account -> its permissions.
_adminRoles: Map<Bytes<32>, Bytes<32>>
ledger
#Mapping from a role identifier to an admin role identifier.
DEFAULT_ADMIN_ROLE: Bytes<32>
ledger
#The default Bytes<32>
value mimicking a constant.
Witnesses
None.
Circuits
hasRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>) → Boolean
circuit
#Returns true
if account
has been granted roleId
.
assertOnlyRole(roleId: Bytes<32>) → []
circuit
#Reverts if caller is missing roleId
.
Requirements:
- The caller must have
roleId
. - The caller must not be a
ContractAddress
.
_checkRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>) → []
circuit
#Reverts if account
is missing roleId
.
Requirements:
account
must haveroleId
.
getRoleAdmin(roleId: Bytes<32>) → Bytes<32>
circuit
#Returns the admin role that controls roleId
or a byte array with all zero bytes if roleId
doesn’t exist.
See grantRole and revokeRole.
To change a role's admin use _setRoleAdmin.
grantRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>) → []
circuit
#Grants roleId
to account
.
Granting roles to contract addresses is currently disallowed until contract-to-contract interactions are supported in Compact. This restriction prevents permanently disabling access to a circuit.
Requirements:
account
must not be a ContractAddress.- The caller must have
roleId
’s admin role.
revokeRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>) → []
circuit
#Revokes roleId
from account
.
Requirements:
- The caller must have
roleId
’s admin role.
renounceRole(
roleId: Bytes<32>,
callerConfirmation: Either<ZswapCoinPublicKey, ContractAddress>
) → []
circuit
#Revokes roleId
from the calling account.
Roles are often managed via grantRole and revokeRole: this circuit’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced).
We do not provide functionality for smart contracts to renounce roles because self-executing transactions are not supported on Midnight at this time. We may revisit this in future if this feature is made available in Compact.
Requirements:
- The caller must be
callerConfirmation
. - The caller must not be a
ContractAddress
.
_setRoleAdmin(roleId: Bytes<32>, adminRole: Bytes<32>) → []
circuit
#Sets adminRole
as roleId
’s admin role.
_grantRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>) → Boolean
circuit
#Attempts to grant roleId
to account
and returns a boolean indicating if roleId
was granted.
Internal circuit without access restriction.
Granting roles to contract addresses is currently disallowed in this circuit until contract-to-contract interactions are supported in Compact. This restriction prevents permanently disabling access to a circuit.
Requirements:
account
must not be a ContractAddress.
_unsafeGrantRole(
roleId: Bytes<32>,
account: Either<ZswapCoinPublicKey, ContractAddress>
) → Boolean
circuit
#Unsafe variant of _grantRole.
Granting roles to contract addresses is considered unsafe because contract-to-contract calls are not currently supported. Granting a role to a smart contract may render a circuit permanently inaccessible. Once contract-to-contract calls are supported, this circuit may be deprecated.
_revokeRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>) → Boolean
circuit
#Attempts to revoke roleId
from account
and returns a boolean indicating if roleId
was revoked.
Internal circuit without access restriction.