ZeroExGovernor

October 19, 2020 ยท View on GitHub

The ZeroExGovernor is a time-locked multi-signature wallet that has permission to perform administrative functions within the protocol. By default, submitted transactions must pass a 14 day timelock before they are executed. However, the ZeroExGovernor also allows custom timelocks to be registered to arbitrary function calls at different destination addresses. Many functions that can be used to mitigate damage in case of emergencies (for example, if a vulnerability is discovered that puts user funds at risk) do not have a timelock. Other functions that affect the system of staking contracts have timelocks that are denominated in terms of 10 day epochs in order to maximize security of upgrades.

The ZeroExGovernor has authorizations to perform the following functions within the protocol:

Managing ownership of all contracts

The ZeroExGovernor can transfer ownership of any contract for which it is the owner by calling the following function:

/// @dev Transfers ownership to a new address.
/// @param newOwner Address of the new owner.
function transferOwnership(address newOwner)
    public;

Managing authorizations in the StakingProxy, ZrxVault, and AssetProxy contracts

Most AssetProxy require that the caller of their transferFrom function is authorized to make the call. The ZeroExGovernor is responsible for adding or removing authorizations (and may bypass the timelock when removing an authorization). This is also the mechanism used for upgrading the Exchange contract without redeploying each individual AssetProxy. A new Exchange contract can be authorized while the authorizations of old Exchange contracts are removed. Multiple contracts can also be simultaneously authorized.

The ZeroExGovernor can also manage authorizations for the StakingProxy and ZrxVault contracts. While the ZeroExGovernor itself is currently the only authorized address in these contracts, this feature can be used to allow new contracts to perform admin functions under different conditions in the future (such as with an on-chain token vote).

Registering AssetProxy contracts in the Exchange and MultiAssetProxy

AssetProxy contracts must be registered in the Exchange and MultiAssetProxy contracts in order to be utilized when filling orders. The ZeroExGovernor can register new AssetProxy contracts by calling the following function:

/// @dev Registers an asset proxy to its asset proxy id.
///      Once an asset proxy is registered, it cannot be unregistered.
/// @param assetProxy Address of new asset proxy to register.
function registerAssetProxy(address assetProxy)
    external;

Setting the protocol fee multiplier in the Exchange

The ZeroExGovernor can update the protocol fee multiplier by calling the following function:

/// @dev Allows the owner to update the protocol fee multiplier.
/// @param updatedProtocolFeeMultiplier The updated protocol fee multiplier.
function setProtocolFeeMultiplier(uint256 updatedProtocolFeeMultiplier)
    external;

Setting the protocolFeeMultiplier will emit a ProtocolFeeMultiplier event.

Setting the protocol fee collector (StakingProxy) in the Exchange

The ZeroExGovernor can update the protocol fee collector contract (currently the Staking contract) by calling either of the following functions:

/// @dev Allows the owner to update the protocolFeeCollector address.
/// @param updatedProtocolFeeCollector The updated protocolFeeCollector contract address.
function setProtocolFeeCollectorAddress(address updatedProtocolFeeCollector)
    external;

/// @dev Sets the protocolFeeCollector contract address to 0.
///      Only callable by owner.
function detachProtocolFeeCollector()
    external;

Setting the protocolFeeCollector will emit a ProtocolFeeCollectorAddress event.

Updating staking parameters in the StakingProxy

The ZeroExGovernor can update individual staking parameters by calling the following function:

/// @dev Set all configurable parameters at once.
/// @param _epochDurationInSeconds Minimum seconds between epochs.
/// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
/// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
function setParams(
    uint256 _epochDurationInSeconds,
    uint32 _rewardDelegatedStakeWeight,
    uint256 _minimumPoolStake,
    uint32 _cobbDouglasAlphaNumerator,
    uint32 _cobbDouglasAlphaDenominator
)
    external;

Adding or removing Exchange contracts that are allowed to pay protocol fees to the StakingProxy

The ZeroExGovernor can add or remove an Exchange contract from the StakingProxy by calling either of the following functions:

/// @dev Adds a new exchange address
/// @param addr Address of exchange contract to add
function addExchangeAddress(address addr)
    external;

/// @dev Removes an existing exchange address
/// @param addr Address of exchange contract to remove
function removeExchangeAddress(address addr)
    external;

Upgrading the staking logic contract that is attached to the StakingProxy

The ZeroExGovernor can upgrade the logic of the StakingProxy by calling either of the following functions:

/// @dev Attach a staking contract; future calls will be delegated to the staking contract.
/// Note that this is callable only by an authorized address.
/// @param _stakingContract Address of staking contract.
function attachStakingContract(address _stakingContract)
    external;

/// @dev Detach the current staking contract.
/// Note that this is callable only by an authorized address.
function detachStakingContract()
    external;

Setting the StakingProxy that is allowed to trigger deposits and withdrawals from the ZrxVault

The ZeroExGovernor can replace the StakingProxy contract that triggers deposits and withdrawals in the ZrxVault by calling the following function:

/// @dev Sets the address of the StakingProxy contract.
/// Note that only the contract owner can call this function.
/// @param _stakingProxyAddress Address of Staking proxy contract.
function setStakingProxy(address _stakingProxyAddress)
    external;

Setting the AssetProxy that is used used to deposit to the ZrxVault

The ZeroExGovernor can replace the AssetProxy contract used to perform deposits into the ZrxVault by calling the following function:

/// @dev Sets the Zrx proxy.
/// Note that only an authorized address can call this function.
/// Note that this can only be called when *not* in Catastrophic Failure mode.
/// @param _zrxProxyAddress Address of the 0x Zrx Proxy.
function setZrxProxy(address _zrxProxyAddress)
    external;

Entering catastrophic failure mode in the ZrxVault

The ZeroExGovernor can enter catastrophic failure mode in the ZrxVault in emergencies by calling the following function:

/// @dev Vault enters into Catastrophic Failure Mode.
/// *** WARNING - ONCE IN CATOSTROPHIC FAILURE MODE, YOU CAN NEVER GO BACK! ***
/// Note that only the contract owner can call this function.
function enterCatastrophicFailure()
    external;

List of all administrative functions and timelocks

Function timelocks are represented in days, where one day is equivalent to 86,400 seconds. Custom timelocks are in bold.

ContractFunctionSelectorTimelock
ExchangeregisterAssetProxyc585bb9314 days
ExchangesetProtocolFeeMultiplier9331c7427 days
ExchangesetProtocolFeeCollectorAddressc0fa16cc14 days
ExchangedetachProtocolFeeCollector0efca1850 days
ExchangetransferOwnershipf2fde38b14 days
StakingProxyaddExchangeAddress8a2e271a14 days
StakingProxyremoveExchangeAddress01e28d8414 days
StakingProxyattachStakingContract66615d5614 days
StakingProxydetachStakingContract37b006a614 days
StakingProxysetParams9c3ccc827 days
StakingProxyaddAuthorizedAddress42f1181e14 days
StakingProxyremoveAuthorizedAddress7071293914 days
StakingProxyremoveAuthorizedAddressAtIndex9ad2674414 days
StakingProxytransferOwnershipf2fde38b14 days
ZrxVaultsetStakingProxy6bf3f9e514 days
ZrxVaultenterCatastrophicFailurec02e5a7f0 days
ZrxVaultsetZrxProxyca5b021814 days
ZrxVaultaddAuthorizedAddress42f1181e14 days
ZrxVaultremoveAuthorizedAddress7071293914 days
ZrxVaultremoveAuthorizedAddressAtIndex9ad2674414 days
ZrxVaulttransferOwnershipf2fde38b14 days
ERC20ProxyaddAuthorizedAddress42f1181e14 days
ERC20ProxyremoveAuthorizedAddress707129390 days
ERC20ProxyremoveAuthorizedAddressAtIndex9ad267440 days
ERC20ProxytransferOwnershipf2fde38b14 days
ERC721ProxyaddAuthorizedAddress42f1181e14 days
ERC721ProxyremoveAuthorizedAddress707129390 days
ERC721ProxyremoveAuthorizedAddressAtIndex9ad267440 days
ERC721ProxytransferOwnershipf2fde38b14 days
ERC1155ProxyaddAuthorizedAddress42f1181e14 days
ERC1155ProxyremoveAuthorizedAddress707129390 days
ERC1155ProxyremoveAuthorizedAddressAtIndex9ad267440 days
ERC1155ProxytransferOwnershipf2fde38b14 days
ERC20BridgeProxyaddAuthorizedAddress42f1181e14 days
ERC20BridgeProxyremoveAuthorizedAddress707129390 days
ERC20BridgeProxyremoveAuthorizedAddressAtIndex9ad267440 days
ERC20BridgeProxytransferOwnershipf2fde38b14 days
MultiAssetProxyaddAuthorizedAddress42f1181e14 days
MultiAssetProxyremoveAuthorizedAddress707129390 days
MultiAssetProxyremoveAuthorizedAddressAtIndex9ad267440 days
MultiAssetProxytransferOwnershipf2fde38b14 days
MultiAssetProxyregisterAssetProxyc585bb9314 days