Access
This document is better viewed at https://docs.openzeppelin.com/contracts/api/access |
This directory provides ways to restrict who can access the functions of a contract or when they can do it.
-
AccessControl
provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts. -
Ownable
is a simpler mechanism with a single owner "role" that can be assigned to a single account. This simpler mechanism can be useful for quick tests but projects with production concerns are likely to outgrow it. -
TimelockController
is used in combination with one of the above two mechanisms. By assigning a role to an instance of theTimelockController
contract, the access to the functions controlled by that role will be delayed by some amount of time.
Authorization
Ownable
Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions.
By default, the owner account will be the one that deploys the contract. This
can later be changed with transferOwnership
.
This module is used through inheritance. It will make available the modifier
onlyOwner
, which can be applied to your functions to restrict their use to
the owner.
renounceOwnership()
public
Leaves the contract without owner. It will not be possible to call
onlyOwner
functions anymore. Can only be called by the current owner.
Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner. |
AccessControl
Contract module that allows children to implement role-based access control mechanisms.
Roles are referred to by their bytes32
identifier. These should be exposed
in the external API and be unique. The best way to achieve this is by
using public constant
hash digests:
bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
Roles can be used to represent a set of permissions. To restrict access to a
function call, use hasRole
:
function foo() public {
require(hasRole(MY_ROLE, msg.sender));
...
}
Roles can be granted and revoked dynamically via the grantRole
and
revokeRole
functions. 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
.
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.
|
getRoleMemberCount(bytes32 role) → uint256
public
Returns the number of accounts that have role
. Can be used
together with getRoleMember
to enumerate all bearers of a role.
getRoleMember(bytes32 role, uint256 index) → address
public
Returns one of the accounts that have role
. index
must be a
value between 0 and getRoleMemberCount
, non-inclusive.
Role bearers are not sorted in any particular way, and their ordering may change at any point.
When using getRoleMember and getRoleMemberCount , make sure
you perform all queries on the same block. See the following
forum post
for more information.
|
getRoleAdmin(bytes32 role) → bytes32
public
Returns the admin role that controls role
. See grantRole
and
revokeRole
.
To change a role’s admin, use _setRoleAdmin
.
grantRole(bytes32 role, address account)
public
Grants role
to account
.
If account
had not been already granted role
, emits a RoleGranted
event.
Requirements:
-
the caller must have
role
's admin role.
revokeRole(bytes32 role, address account)
public
Revokes role
from account
.
If account
had been granted role
, emits a RoleRevoked
event.
Requirements:
-
the caller must have
role
's admin role.
renounceRole(bytes32 role, address account)
public
Revokes role
from the calling account.
Roles are often managed via grantRole
and revokeRole
: this function’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).
If the calling account had been granted role
, emits a RoleRevoked
event.
Requirements:
-
the caller must be
account
.
_setupRole(bytes32 role, address account)
internal
Grants role
to account
.
If account
had not been already granted role
, emits a RoleGranted
event. Note that unlike grantRole
, this function doesn’t perform any
checks on the calling account.
This function should only be called from the constructor when setting up the initial roles for the system. Using this function in any other way is effectively circumventing the admin
system imposed by |
_setRoleAdmin(bytes32 role, bytes32 adminRole)
internal
Sets adminRole
as role
's admin role.
Emits a RoleAdminChanged
event.
RoleAdminChanged(bytes32 role, bytes32 previousAdminRole, bytes32 newAdminRole)
event
Emitted when newAdminRole
is set as role
's admin role, replacing previousAdminRole
DEFAULT_ADMIN_ROLE
is the starting admin for all roles, despite
RoleAdminChanged
not being emitted signaling this.
Available since v3.1.
RoleGranted(bytes32 role, address account, address sender)
event
Emitted when account
is granted role
.
sender
is the account that originated the contract call, an admin role
bearer except when using _setupRole
.
Timelock
TimelockController
Contract module which acts as a timelocked controller. When set as the
owner of an Ownable
smart contract, it enforces a timelock on all
onlyOwner
maintenance operations. This gives time for users of the
controlled contract to exit before a potentially dangerous maintenance
operation is applied.
By default, this contract is self administered, meaning administration tasks
have to go through the timelock process. The proposer (resp executor) role
is in charge of proposing (resp executing) operations. A common use case is
to position this TimelockController
as the owner of a smart contract, with
a multisig or a DAO as the sole proposer.
Available since v3.3.
onlyRole(bytes32 role)
modifier
Modifier to make a function callable only by a certain role. In
addition to checking the sender’s role, address(0)
's role is also
considered. Granting a role to address(0)
is equivalent to enabling
this role for everyone.
constructor(uint256 minDelay, address[] proposers, address[] executors)
public
Initializes the contract with a given minDelay
.
isOperation(bytes32 id) → bool pending
public
Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations.
isOperationPending(bytes32 id) → bool pending
public
Returns whether an operation is pending or not.
getTimestamp(bytes32 id) → uint256 timestamp
public
Returns the timestamp at with an operation becomes ready (0 for unset operations, 1 for done operations).
getMinDelay() → uint256 duration
public
Returns the minimum delay for an operation to become valid.
This value can be changed by executing an operation that calls updateDelay
.
hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) → bytes32 hash
public
Returns the identifier of an operation containing a single transaction.
hashOperationBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt) → bytes32 hash
public
Returns the identifier of an operation containing a batch of transactions.
schedule(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt, uint256 delay)
public
Schedule an operation containing a single transaction.
Emits a CallScheduled
event.
Requirements:
-
the caller must have the 'proposer' role.
scheduleBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt, uint256 delay)
public
Schedule an operation containing a batch of transactions.
Emits one CallScheduled
event per transaction in the batch.
Requirements:
-
the caller must have the 'proposer' role.
cancel(bytes32 id)
public
Cancel an operation.
Requirements:
-
the caller must have the 'proposer' role.
execute(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt)
public
Execute an (ready) operation containing a single transaction.
Emits a CallExecuted
event.
Requirements:
-
the caller must have the 'executor' role.
executeBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt)
public
Execute an (ready) operation containing a batch of transactions.
Emits one CallExecuted
event per transaction in the batch.
Requirements:
-
the caller must have the 'executor' role.
updateDelay(uint256 newDelay)
external
Changes the minimum timelock duration for future operations.
Emits a MinDelayChange
event.
Requirements:
-
the caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the ABI-encoded call to this function.
CallScheduled(bytes32 id, uint256 index, address target, uint256 value, bytes data, bytes32 predecessor, uint256 delay)
event
Emitted when a call is scheduled as part of operation id
.
CallExecuted(bytes32 id, uint256 index, address target, uint256 value, bytes data)
event
Emitted when a call is performed as part of operation id
.
MinDelayChange(uint256 oldDuration, uint256 newDuration)
event
Emitted when the minimum delay for future operations is modified.
Terminology
-
Operation: A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution (see operation lifecycle). If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content.
-
Operation status:
-
Unset: An operation that is not part of the timelock mechanism.
-
Pending: An operation that has been scheduled, before the timer expires.
-
Ready: An operation that has been scheduled, after the timer expires.
-
Done: An operation that has been executed.
-
-
Predecessor: An (optional) dependency between operations. An operation can depend on another operation (its predecessor), forcing the execution order of these two operations.
-
Role:
-
Proposer: An address (smart contract or EOA) that is in charge of scheduling (and cancelling) operations.
-
Executor: An address (smart contract or EOA) that is in charge of executing operations.
-
Operation structure
Operation executed by the TimelockControler
can contain one or multiple subsequent calls. Depending on whether you need to multiple calls to be executed atomically, you can either use simple or batched operations.
Both operations contain:
-
Target, the address of the smart contract that the timelock should operate on.
-
Value, in wei, that should be sent with the transaction. Most of the time this will be 0. Ether can be deposited before-end or passed along when executing the transaction.
-
Data, containing the encoded function selector and parameters of the call. This can be produced using a number of tools. For example, a maintenance operation granting role
ROLE
toACCOUNT
can be encode using web3js as follows:
const data = timelock.contract.methods.grantRole(ROLE, ACCOUNT).encodeABI()
-
Predecessor, that specifies a dependency between operations. This dependency is optional. Use
bytes32(0)
if the operation does not have any dependency. -
Salt, used to disambiguate two otherwise identical operations. This can be any random value.
In the case of batched operations, target
, value
and data
are specified as arrays, which must be of the same length.
Operation lifecycle
Timelocked operations are identified by a unique id (their hash) and follow a specific lifecycle:
Unset
→ Pending
→ Pending
+ Ready
→ Done
-
By calling
schedule
(orscheduleBatch
), a proposer moves the operation from theUnset
to thePending
state. This starts a timer that must be longer than the minimum delay. The timer expires at a timestamp accessible through thegetTimestamp
method. -
Once the timer expires, the operation automatically gets the
Ready
state. At this point, it can be executed. -
By calling
execute
(orexecuteBatch
), an executor triggers the operation’s underlying transactions and moves it to theDone
state. If the operation has a predecessor, it has to be in theDone
state for this transition to succeed. -
cancel
allows proposers to cancel anyPending
operation. This resets the operation to theUnset
state. It is thus possible for a proposer to re-schedule an operation that has been cancelled. In this case, the timer restarts when the operation is re-scheduled.
Operations status can be queried using the functions:
Roles
Admin
The admins are in charge of managing proposers and executors. For the timelock to be self-governed, this role should only be given to the timelock itself. Upon deployment, both the timelock and the deployer have this role. After further configuration and testing, the deployer can renounce this role such that all further maintenance operations have to go through the timelock process.
This role is identified by the TIMELOCK_ADMIN_ROLE value: 0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5
Proposer
The proposers are in charge of scheduling (and cancelling) operations. This is a critical role, that should be given to governing entities. This could be an EOA, a multisig, or a DAO.
Proposer fight: Having multiple proposers, while providing redundancy in case one becomes unavailable, can be dangerous. As proposer have their say on all operations, they could cancel operations they disagree with, including operations to remove them for the proposers. |
This role is identified by the PROPOSER_ROLE value: 0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1
Executor
The executors are in charge of executing the operations scheduled by the proposers once the timelock expires. Logic dictates that multisig or DAO that are proposers should also be executors in order to guarantee operations that have been scheduled will eventually be executed. However, having additional executor can reduce the cost (the executing transaction does not require validation by the multisig or DAO that proposed it), while ensuring whoever is in charge of execution cannot trigger actions that have not been scheduled by the proposers.
This role is identified by the EXECUTOR_ROLE value: 0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63
A live contract without at least one proposer and one executor is locked. Make sure these roles are filled by reliable entities before the deployer renounces its administrative rights in favour of the timelock contract itself. See the AccessControl documentation to learn more about role management.
|