Quantillon Protocol

Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TimelockUpgradeable

Git Source

Inherits: Initializable, AccessControlUpgradeable, PausableUpgradeable

Author: Quantillon Labs - Nicolas Bellengé - @chewbaccoin

Secure upgrade mechanism with timelock and multi-sig requirements

Replaces unrestricted upgrade capability with governance-controlled upgrades

Note: security-contact: team@quantillon.money

State Variables

UPGRADE_DELAY

Minimum delay for upgrades (48 hours)

uint256 public constant UPGRADE_DELAY = 48 hours

MAX_UPGRADE_DELAY

Maximum delay for upgrades (7 days)

uint256 public constant MAX_UPGRADE_DELAY = 7 days

MIN_MULTISIG_APPROVALS

Minimum number of multi-sig approvals required

uint256 public constant MIN_MULTISIG_APPROVALS = 2

MAX_MULTISIG_SIGNERS

Maximum number of multi-sig signers

uint256 public constant MAX_MULTISIG_SIGNERS = 5

UPGRADE_PROPOSER_ROLE

Role for proposing upgrades

bytes32 public constant UPGRADE_PROPOSER_ROLE = keccak256("UPGRADE_PROPOSER_ROLE")

UPGRADE_EXECUTOR_ROLE

Role for executing upgrades after timelock

bytes32 public constant UPGRADE_EXECUTOR_ROLE = keccak256("UPGRADE_EXECUTOR_ROLE")

EMERGENCY_UPGRADER_ROLE

Role for emergency upgrades (bypasses timelock)

bytes32 public constant EMERGENCY_UPGRADER_ROLE = keccak256("EMERGENCY_UPGRADER_ROLE")

MULTISIG_MANAGER_ROLE

Role for managing multi-sig signers

bytes32 public constant MULTISIG_MANAGER_ROLE = keccak256("MULTISIG_MANAGER_ROLE")

pendingUpgrades

Pending upgrades by implementation address

mapping(address => PendingUpgrade) public pendingUpgrades

multisigSigners

Multi-sig signers

mapping(address => bool) public multisigSigners

multisigSignerCount

Number of active multi-sig signers

uint256 public multisigSignerCount

upgradeApprovals

Upgrade approvals by signer

mapping(address => mapping(address => bool)) public upgradeApprovals

upgradeApprovalCount

Number of approvals for each pending upgrade

mapping(address => uint256) public upgradeApprovalCount

emergencyMode

Whether emergency mode is active

bool public emergencyMode

TIME_PROVIDER

TimeProvider contract for centralized time management

Used to replace direct block.timestamp usage for testability and consistency

TimeProvider public immutable TIME_PROVIDER

Functions

onlyMultisigSigner

modifier onlyMultisigSigner() ;

onlyEmergencyUpgrader

modifier onlyEmergencyUpgrader() ;

initialize

Initializes the timelock contract with admin privileges

Sets up access control roles and pausability. Can only be called once.

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to initializer modifier

  • oracle: No oracle dependencies

function initialize(address admin) public initializer;

Parameters

NameTypeDescription
adminaddressThe address that will receive admin and upgrade proposer roles

proposeUpgrade

Propose an upgrade with timelock

Proposes an upgrade with timelock delay and multi-sig approval requirements

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to UPGRADE_PROPOSER_ROLE

  • oracle: No oracle dependencies

function proposeUpgrade(address newImplementation, string calldata description, uint256 customDelay)
    external
    onlyRole(UPGRADE_PROPOSER_ROLE);

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the upgrade
customDelayuint256Optional custom delay (must be >= UPGRADE_DELAY)

approveUpgrade

Approve a pending upgrade (multi-sig signer only)

Allows multi-sig signers to approve pending upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to multi-sig signers

  • oracle: No oracle dependencies

function approveUpgrade(address implementation) external onlyMultisigSigner;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to approve

revokeUpgradeApproval

Revoke approval for a pending upgrade

Allows multi-sig signers to revoke their approval for pending upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to multi-sig signers

  • oracle: No oracle dependencies

function revokeUpgradeApproval(address implementation) external onlyMultisigSigner;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to revoke approval for

executeUpgrade

Execute an upgrade after timelock and multi-sig approval

Executes an upgrade after timelock delay and sufficient multi-sig approvals

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to UPGRADE_EXECUTOR_ROLE

  • oracle: No oracle dependencies

function executeUpgrade(address implementation) external onlyRole(UPGRADE_EXECUTOR_ROLE);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to execute

cancelUpgrade

Cancel a pending upgrade (only proposer or admin)

Allows proposer or admin to cancel pending upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to proposer or admin

  • oracle: No oracle dependencies

function cancelUpgrade(address implementation) external;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation to cancel

emergencyUpgrade

Emergency upgrade (bypasses timelock, requires emergency mode)

Performs emergency upgrade bypassing timelock and multi-sig requirements

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to emergency upgrader role

  • oracle: No oracle dependencies

function emergencyUpgrade(address newImplementation, string calldata description) external onlyEmergencyUpgrader;

Parameters

NameTypeDescription
newImplementationaddressAddress of the new implementation
descriptionstringDescription of the emergency upgrade

addMultisigSigner

Add a multi-sig signer

Adds a new multi-sig signer to the timelock system

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to MULTISIG_MANAGER_ROLE

  • oracle: No oracle dependencies

function addMultisigSigner(address signer) external onlyRole(MULTISIG_MANAGER_ROLE);

Parameters

NameTypeDescription
signeraddressAddress of the signer to add

removeMultisigSigner

Remove a multi-sig signer

Removes a multi-sig signer from the timelock system

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to MULTISIG_MANAGER_ROLE

  • oracle: No oracle dependencies

function removeMultisigSigner(address signer) external onlyRole(MULTISIG_MANAGER_ROLE);

Parameters

NameTypeDescription
signeraddressAddress of the signer to remove

toggleEmergencyMode

Toggle emergency mode

Toggles emergency mode for emergency upgrades

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to EMERGENCY_UPGRADER_ROLE

  • oracle: No oracle dependencies

function toggleEmergencyMode(bool enabled, string calldata reason) external onlyRole(EMERGENCY_UPGRADER_ROLE);

Parameters

NameTypeDescription
enabledboolWhether to enable emergency mode
reasonstringReason for the emergency mode change

getPendingUpgrade

Get pending upgrade details

Returns pending upgrade details for a given implementation

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function getPendingUpgrade(address implementation) external view returns (PendingUpgrade memory upgrade);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
upgradePendingUpgradePending upgrade details

canExecuteUpgrade

Check if an upgrade can be executed

Checks if an upgrade can be executed based on timelock and approval requirements

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function canExecuteUpgrade(address implementation) external view returns (bool canExecute);

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

Returns

NameTypeDescription
canExecuteboolWhether the upgrade can be executed

hasUpgradeApproval

Get upgrade approval status for a signer

Returns whether a signer has approved a specific upgrade

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function hasUpgradeApproval(address signer, address implementation) external view returns (bool approved);

Parameters

NameTypeDescription
signeraddressAddress of the signer
implementationaddressAddress of the implementation

Returns

NameTypeDescription
approvedboolWhether the signer has approved the upgrade

getMultisigSigners

Get all multi-sig signers

Returns array of all multi-sig signer addresses

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: No state changes

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

function getMultisigSigners() external view returns (address[] memory signers);

Returns

NameTypeDescription
signersaddress[]Array of signer addresses

_clearUpgradeApprovals

Clear all approvals for an implementation

Clears all approvals for a specific implementation

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _clearUpgradeApprovals(address implementation) internal;

Parameters

NameTypeDescription
implementationaddressAddress of the implementation

_clearSignerApprovals

Clear all approvals from a specific signer

Clears all approvals from a specific signer

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _clearSignerApprovals(address signer) internal;

Parameters

NameTypeDescription
signeraddressAddress of the signer

_addMultisigSigner

Add a multisig signer (internal)

Adds a multisig signer internally

Notes:

  • security: No security checks needed

  • validation: No validation needed

  • state-changes: Updates contract state variables

  • events: No events emitted

  • errors: No errors thrown

  • reentrancy: No reentrancy protection needed

  • access: Internal function

  • oracle: No oracle dependencies

function _addMultisigSigner(address signer) internal;

Parameters

NameTypeDescription
signeraddressAddress of the signer

pause

Pause the timelock contract

Pauses the timelock contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function pause() external onlyRole(DEFAULT_ADMIN_ROLE);

unpause

Unpause the timelock contract

Unpauses the timelock contract

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Updates contract state variables

  • events: Emits relevant events for state changes

  • errors: Throws custom errors for invalid conditions

  • reentrancy: Protected by reentrancy guard

  • access: Restricted to DEFAULT_ADMIN_ROLE

  • oracle: No oracle dependencies

function unpause() external onlyRole(DEFAULT_ADMIN_ROLE);

constructor

Constructor for TimelockUpgradeable contract

Sets up the time provider and disables initializers for security

Notes:

  • security: Validates input parameters and enforces security checks

  • validation: Validates input parameters and business logic constraints

  • state-changes: Disables initializers

  • events: No events emitted

  • errors: Throws custom errors for invalid conditions

  • reentrancy: No reentrancy protection needed

  • access: No access restrictions

  • oracle: No oracle dependencies

constructor(TimeProvider _TIME_PROVIDER) ;

Parameters

NameTypeDescription
_TIME_PROVIDERTimeProviderTimeProvider contract for centralized time management

Events

UpgradeProposed

event UpgradeProposed(
    address indexed implementation,
    uint256 proposedAt,
    uint256 executableAt,
    string description,
    address indexed proposer
);

UpgradeApproved

event UpgradeApproved(address indexed implementation, address indexed signer, uint256 approvalCount);

UpgradeExecuted

event UpgradeExecuted(address indexed implementation, address indexed executor, uint256 executedAt);

UpgradeCancelled

event UpgradeCancelled(address indexed implementation, address indexed canceller);

MultisigSignerAdded

event MultisigSignerAdded(address indexed signer);

MultisigSignerRemoved

event MultisigSignerRemoved(address indexed signer);

EmergencyModeToggled

event EmergencyModeToggled(bool enabled, string reason);

Structs

PendingUpgrade

struct PendingUpgrade {
    address implementation;
    uint256 proposedAt;
    uint256 executableAt;
    string description;
    bool isEmergency;
    address proposer;
}