Skip to content

Latest commit

 

History

History
890 lines (720 loc) · 24.5 KB

TimelockController.md

File metadata and controls

890 lines (720 loc) · 24.5 KB

TimelockController.sol

View Source: openzeppelin-solidity/contracts/governance/TimelockController.sol

↗ Extends: AccessControl ↘ Derived Contracts: Delayable

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.

Contract Members

Constants & Variables

//public members
bytes32 public constant TIMELOCK_ADMIN_ROLE;
bytes32 public constant PROPOSER_ROLE;
bytes32 public constant EXECUTOR_ROLE;

//internal members
uint256 internal constant _DONE_TIMESTAMP;

//private members
mapping(bytes32 => uint256) private _timestamps;
uint256 private _minDelay;

Events

event CallScheduled(bytes32 indexed id, uint256 indexed index, address  target, uint256  value, bytes  data, bytes32  predecessor, uint256  delay);
event CallExecuted(bytes32 indexed id, uint256 indexed index, address  target, uint256  value, bytes  data);
event Cancelled(bytes32 indexed id);
event MinDelayChange(uint256  oldDuration, uint256  newDuration);

Modifiers

onlyRoleOrOpenRole

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.

modifier onlyRoleOrOpenRole(bytes32 role) internal

Arguments

Name Type Description
role bytes32

Functions

Initializes the contract with a given minDelay.

function (uint256 minDelay, address[] proposers, address[] executors) public nonpayable

Arguments

Name Type Description
minDelay uint256
proposers address[]
executors address[]
Source Code
constructor(
        uint256 minDelay,
        address[] memory proposers,
        address[] memory executors
    ) {
        _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
        _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
        _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);

        // deployer + self administration
        _setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());
        _setupRole(TIMELOCK_ADMIN_ROLE, address(this));

        // register proposers
        for (uint256 i = 0; i < proposers.length; ++i) {
            _setupRole(PROPOSER_ROLE, proposers[i]);
        }

        // register executors
        for (uint256 i = 0; i < executors.length; ++i) {
            _setupRole(EXECUTOR_ROLE, executors[i]);
        }

        _minDelay = minDelay;
        emit MinDelayChange(0, minDelay);
    }

Contract might receive/hold ETH as part of the maintenance process.

function () external payable

Arguments

Name Type Description
Source Code
receive() external payable {}

isOperation

Returns whether an id correspond to a registered operation. This includes both Pending, Ready and Done operations.

function isOperation(bytes32 id) public view
returns(pending bool)

Arguments

Name Type Description
id bytes32
Source Code
function isOperation(bytes32 id) public view virtual returns (bool pending) {
        return getTimestamp(id) > 0;
    }

isOperationPending

Returns whether an operation is pending or not.

function isOperationPending(bytes32 id) public view
returns(pending bool)

Arguments

Name Type Description
id bytes32
Source Code
function isOperationPending(bytes32 id) public view virtual returns (bool pending) {
        return getTimestamp(id) > _DONE_TIMESTAMP;
    }

isOperationReady

Returns whether an operation is ready or not.

function isOperationReady(bytes32 id) public view
returns(ready bool)

Arguments

Name Type Description
id bytes32
Source Code
function isOperationReady(bytes32 id) public view virtual returns (bool ready) {
        uint256 timestamp = getTimestamp(id);
        return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;
    }

isOperationDone

Returns whether an operation is done or not.

function isOperationDone(bytes32 id) public view
returns(done bool)

Arguments

Name Type Description
id bytes32
Source Code
function isOperationDone(bytes32 id) public view virtual returns (bool done) {
        return getTimestamp(id) == _DONE_TIMESTAMP;
    }

getTimestamp

Returns the timestamp at with an operation becomes ready (0 for unset operations, 1 for done operations).

function getTimestamp(bytes32 id) public view
returns(timestamp uint256)

Arguments

Name Type Description
id bytes32
Source Code
function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp) {
        return _timestamps[id];
    }

getMinDelay

Returns the minimum delay for an operation to become valid. This value can be changed by executing an operation that calls updateDelay.

function getMinDelay() public view
returns(duration uint256)

Arguments

Name Type Description
Source Code
function getMinDelay() public view virtual returns (uint256 duration) {
        return _minDelay;
    }

hashOperation

Returns the identifier of an operation containing a single transaction.

function hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) public pure
returns(hash bytes32)

Arguments

Name Type Description
target address
value uint256
data bytes
predecessor bytes32
salt bytes32
Source Code
function hashOperation(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32 hash) {
        return keccak256(abi.encode(target, value, data, predecessor, salt));
    }

hashOperationBatch

Returns the identifier of an operation containing a batch of transactions.

function hashOperationBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt) public pure
returns(hash bytes32)

Arguments

Name Type Description
targets address[]
values uint256[]
datas bytes[]
predecessor bytes32
salt bytes32
Source Code
function hashOperationBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata datas,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32 hash) {
        return keccak256(abi.encode(targets, values, datas, predecessor, salt));
    }

schedule

Schedule an operation containing a single transaction. Emits a {CallScheduled} event. Requirements:

  • the caller must have the 'proposer' role.
function schedule(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt, uint256 delay) public nonpayable onlyRole 

Arguments

Name Type Description
target address
value uint256
data bytes
predecessor bytes32
salt bytes32
delay uint256
Source Code
function schedule(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        bytes32 id = hashOperation(target, value, data, predecessor, salt);
        _schedule(id, delay);
        emit CallScheduled(id, 0, target, value, data, predecessor, delay);
    }

scheduleBatch

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.
function scheduleBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt, uint256 delay) public nonpayable onlyRole 

Arguments

Name Type Description
targets address[]
values uint256[]
datas bytes[]
predecessor bytes32
salt bytes32
delay uint256
Source Code
function scheduleBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata datas,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        require(targets.length == values.length, "TimelockController: length mismatch");
        require(targets.length == datas.length, "TimelockController: length mismatch");

        bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
        _schedule(id, delay);
        for (uint256 i = 0; i < targets.length; ++i) {
            emit CallScheduled(id, i, targets[i], values[i], datas[i], predecessor, delay);
        }
    }

_schedule

Schedule an operation that is to becomes valid after a given delay.

function _schedule(bytes32 id, uint256 delay) private nonpayable

Arguments

Name Type Description
id bytes32
delay uint256
Source Code
function _schedule(bytes32 id, uint256 delay) private {
        require(!isOperation(id), "TimelockController: operation already scheduled");
        require(delay >= getMinDelay(), "TimelockController: insufficient delay");
        _timestamps[id] = block.timestamp + delay;
    }

cancel

Cancel an operation. Requirements:

  • the caller must have the 'proposer' role.
function cancel(bytes32 id) public nonpayable onlyRole 

Arguments

Name Type Description
id bytes32
Source Code
function cancel(bytes32 id) public virtual onlyRole(PROPOSER_ROLE) {
        require(isOperationPending(id), "TimelockController: operation cannot be cancelled");
        delete _timestamps[id];

        emit Cancelled(id);
    }

execute

Execute an (ready) operation containing a single transaction. Emits a {CallExecuted} event. Requirements:

  • the caller must have the 'executor' role.
function execute(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) public payable onlyRoleOrOpenRole 

Arguments

Name Type Description
target address
value uint256
data bytes
predecessor bytes32
salt bytes32
Source Code
function execute(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        bytes32 id = hashOperation(target, value, data, predecessor, salt);
        _beforeCall(id, predecessor);
        _call(id, 0, target, value, data);
        _afterCall(id);
    }

executeBatch

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.
function executeBatch(address[] targets, uint256[] values, bytes[] datas, bytes32 predecessor, bytes32 salt) public payable onlyRoleOrOpenRole 

Arguments

Name Type Description
targets address[]
values uint256[]
datas bytes[]
predecessor bytes32
salt bytes32
Source Code
function executeBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata datas,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        require(targets.length == values.length, "TimelockController: length mismatch");
        require(targets.length == datas.length, "TimelockController: length mismatch");

        bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
        _beforeCall(id, predecessor);
        for (uint256 i = 0; i < targets.length; ++i) {
            _call(id, i, targets[i], values[i], datas[i]);
        }
        _afterCall(id);
    }

_beforeCall

Checks before execution of an operation's calls.

function _beforeCall(bytes32 id, bytes32 predecessor) private view

Arguments

Name Type Description
id bytes32
predecessor bytes32
Source Code
function _beforeCall(bytes32 id, bytes32 predecessor) private view {
        require(isOperationReady(id), "TimelockController: operation is not ready");
        require(predecessor == bytes32(0) || isOperationDone(predecessor), "TimelockController: missing dependency");
    }

_afterCall

Checks after execution of an operation's calls.

function _afterCall(bytes32 id) private nonpayable

Arguments

Name Type Description
id bytes32
Source Code
function _afterCall(bytes32 id) private {
        require(isOperationReady(id), "TimelockController: operation is not ready");
        _timestamps[id] = _DONE_TIMESTAMP;
    }

_call

Execute an operation's call. Emits a {CallExecuted} event.

function _call(bytes32 id, uint256 index, address target, uint256 value, bytes data) private nonpayable

Arguments

Name Type Description
id bytes32
index uint256
target address
value uint256
data bytes
Source Code
function _call(
        bytes32 id,
        uint256 index,
        address target,
        uint256 value,
        bytes calldata data
    ) private {
        (bool success, ) = target.call{value: value}(data);
        require(success, "TimelockController: underlying transaction reverted");

        emit CallExecuted(id, index, target, value, data);
    }

updateDelay

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.
function updateDelay(uint256 newDelay) external nonpayable

Arguments

Name Type Description
newDelay uint256
Source Code
function updateDelay(uint256 newDelay) external virtual {
        require(msg.sender == address(this), "TimelockController: caller must be timelock");
        emit MinDelayChange(_minDelay, newDelay);
        _minDelay = newDelay;
    }

Contracts