Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0x119FbeeDD4F4f4298Fb59B720d5654442b81ae2c
Balance 0 ETH
Nonce 1
Code Size 3836 bytes
Indexed Transactions 0 (1 on-chain, <1% indexed)
External Etherscan · Sourcify

Contract Bytecode

3836 bytes
Copy Bytecode
0x608060405234801561000f575f80fd5b5060043610610163575f3560e01c8063abf306a8116100c7578063d7d1c1c01161007d578063f294bd9211610063578063f294bd9214610332578063f52c93c514610359578063fbfa77cf14610361575f80fd5b8063d7d1c1c0146102f8578063e94bb2231461030b575f80fd5b8063b3d0c202116100ad578063b3d0c202146102c8578063b4d87a12146102d2578063d48d8423146102e5575f80fd5b8063abf306a814610281578063af63a3e1146102a1575f80fd5b80635548917f1161011c5780638eaa6ac0116101025780638eaa6ac01461024757806391ddadf41461025a5780639662ac5814610279575f80fd5b80635548917f146101f95780638df3227f14610220575f80fd5b80632595f8cf1161014c5780632595f8cf146101945780634bf5d7e9146101b75780634d6d7441146101cc575f80fd5b806307a0033014610167578063246c53081461017c575b5f80fd5b61017a610175366004610b41565b610388565b005b6213c6805b6040519081526020015b60405180910390f35b6101a76101a2366004610ba9565b61042a565b604051901515815260200161018b565b6101bf610514565b60405161018b9190610bf1565b6101d4610523565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161018b565b6101d47f0000000000000000000000003414922ff6edf6aacadb6ab4f2533089144625c481565b6101d47f000000000000000000000000a0dafaeea4a1d44534e1b9227e19cae6358b80fe81565b610181610255366004610c5b565b6105b1565b61026261061f565b60405165ffffffffffff909116815260200161018b565b6101d4610631565b61029461028f366004610c72565b61069b565b60405161018b9190610cb1565b6101d47f000000000000000000000000f6de7fde6f7a8947b94973053b580e754360d2f981565b63661bd350610181565b61017a6102e0366004610d18565b610796565b61017a6102f3366004610d18565b61086b565b6101a7610306366004610d18565b61093f565b6101d47f0000000000000000000000009fff4be0003d0716f37f8d2574e89f1a5d0745c881565b6101d47f000000000000000000000000988567fe094570cce1ffda29d1f2d842b70492be81565b6101d46109e0565b6101d47f000000000000000000000000d7298f620b0f752cf41bd818a16c756d9dcaa34f81565b610390610a4a565b805f806103e9856040517f56414c55450000000000000000000000000000000000000000000000000000006020820152602581018290525f90604501604051602081830303815290604052805190602001209050919050565b81526020019081526020015f20819055827f40d4a420f99fca87993b89b3251153e5ffb22d82a70bf764d19ba9f0621d653560405160405180910390a35050565b5f805b828110156105075760015f806104e38888888781811061044f5761044f610d46565b90506020020160208101906104649190610d73565b6040517f494e5f4c495354000000000000000000000000000000000000000000000000006020820152602781018390527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b1660478201525f90605b0160405160208183030381529060405280519060200120905092915050565b81526020019081526020015f2054146104ff575f91505061050d565b60010161042d565b50600190505b9392505050565b606061051e610af9565b905090565b5f7f0000000000000000000000009fff4be0003d0716f37f8d2574e89f1a5d0745c873ffffffffffffffffffffffffffffffffffffffff1663585e78af6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561058d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061051e9190610d8e565b5f805f61060a846040517f56414c55450000000000000000000000000000000000000000000000000000006020820152602581018290525f90604501604051602081830303815290604052805190602001209050919050565b81526020019081526020015f20549050919050565b5f610628610b19565b61ffff16905090565b5f7f000000000000000000000000f6de7fde6f7a8947b94973053b580e754360d2f973ffffffffffffffffffffffffffffffffffffffff1663585e78af6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561058d573d5f803e3d5ffd5b60608167ffffffffffffffff8111156106b6576106b6610da9565b6040519080825280602002602001820160405280156106df578160200160208202803683370190505b5090505f5b8281101561078f575f8061075c86868581811061070357610703610d46565b905060200201356040517f56414c55450000000000000000000000000000000000000000000000000000006020820152602581018290525f90604501604051602081830303815290604052805190602001209050919050565b81526020019081526020015f205482828151811061077c5761077c610d46565b60209081029190910101526001016106e4565b5092915050565b61079e610a4a565b604080517f494e5f4c49535400000000000000000000000000000000000000000000000000602080830191909152602782018590527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b1660478301528251808303603b018152605b9092018084528251928201929092205f908152908190529182206001905573ffffffffffffffffffffffffffffffffffffffff83169184917f56573e227f8e2cfaf9c513a7e1586b18527b6f4010b703025003741b6a451ad59190a35050565b610873610a4a565b604080517f494e5f4c49535400000000000000000000000000000000000000000000000000602080830191909152602782018590527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b1660478301528251808303603b018152605b9092018084528251928201929092205f9081529081905291822082905573ffffffffffffffffffffffffffffffffffffffff83169184917f72e193b20c528dc6c7ac5d8f5bc4354aa22b592c0fdca040fa926c2ff90534f79190a35050565b5f600181806109c886866040517f494e5f4c495354000000000000000000000000000000000000000000000000006020820152602781018390527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b1660478201525f90605b0160405160208183030381529060405280519060200120905092915050565b81526020019081526020015f20541490505b92915050565b5f7f0000000000000000000000003414922ff6edf6aacadb6ab4f2533089144625c473ffffffffffffffffffffffffffffffffffffffff1663585e78af6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561058d573d5f803e3d5ffd5b610a52610523565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610ac05750610a906109e0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610af7576040517f72fab01a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60606040518060a0016040528060658152602001610e6260659139905090565b5f6213c680610b2c63661bd35042610e03565b610b369190610e16565b61051e906001610e4e565b5f8060408385031215610b52575f80fd5b50508035926020909101359150565b5f8083601f840112610b71575f80fd5b50813567ffffffffffffffff811115610b88575f80fd5b6020830191508360208260051b8501011115610ba2575f80fd5b9250929050565b5f805f60408486031215610bbb575f80fd5b83359250602084013567ffffffffffffffff811115610bd8575f80fd5b610be486828701610b61565b9497909650939450505050565b5f602080835283518060208501525f5b81811015610c1d57858101830151858201604001528201610c01565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b5f60208284031215610c6b575f80fd5b5035919050565b5f8060208385031215610c83575f80fd5b823567ffffffffffffffff811115610c99575f80fd5b610ca585828601610b61565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b81811015610ce857835183529284019291840191600101610ccc565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610d15575f80fd5b50565b5f8060408385031215610d29575f80fd5b823591506020830135610d3b81610cf4565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610d83575f80fd5b813561050d81610cf4565b5f60208284031215610d9e575f80fd5b815161050d81610cf4565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156109da576109da610dd6565b5f82610e49577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b808201808211156109da576109da610dd656fe6d6f64653d65706f63682665706f6368556e6465726c79696e67536f757263653d626c6f636b54696d657374616d702665706f63685374617274696e6754696d657374616d703d313731333039393630302665706f6368506572696f643d31323936303030a26469706673582212200a0c0a55c2e0eb0c25754573a708b569ab026719b289cbf421f59aa7286248d664736f6c63430008170033

Verified Source Code Full Match

Compiler: v0.8.23+commit.f704f362 EVM: shanghai Optimization: Yes (999999 runs)
Registrar.sol 201 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IEmergencyGovernorDeployer } from "./interfaces/IEmergencyGovernorDeployer.sol";
import { IERC6372 } from "./abstract/interfaces/IERC6372.sol";
import { IPowerTokenDeployer } from "./interfaces/IPowerTokenDeployer.sol";
import { IRegistrar } from "./interfaces/IRegistrar.sol";
import { IStandardGovernorDeployer } from "./interfaces/IStandardGovernorDeployer.sol";
import { IZeroGovernor } from "./interfaces/IZeroGovernor.sol";

import { PureEpochs } from "./libs/PureEpochs.sol";

/*

████████╗████████╗ ██████╗     ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗  █████╗ ██████╗
╚══██╔══╝╚══██╔══╝██╔════╝     ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗██╔══██╗██╔══██╗
   ██║      ██║   ██║  ███╗    ██████╔╝█████╗  ██║  ███╗██║███████╗   ██║   ██████╔╝███████║██████╔╝
   ██║      ██║   ██║   ██║    ██╔══██╗██╔══╝  ██║   ██║██║╚════██║   ██║   ██╔══██╗██╔══██║██╔══██╗
   ██║      ██║   ╚██████╔╝    ██║  ██║███████╗╚██████╔╝██║███████║   ██║   ██║  ██║██║  ██║██║  ██║
   ╚═╝      ╚═╝    ╚═════╝     ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝

*/

/**
 * @title  A book of record of TTG-specific contracts and arbitrary key-value pairs and lists.
 * @author M^0 Labs
 */
contract Registrar is IRegistrar {
    /* ============ Variables ============ */

    /// @inheritdoc IRegistrar
    address public immutable emergencyGovernorDeployer;

    /// @inheritdoc IRegistrar
    address public immutable powerTokenDeployer;

    /// @inheritdoc IRegistrar
    address public immutable standardGovernorDeployer;

    /// @inheritdoc IRegistrar
    address public immutable vault;

    /// @inheritdoc IRegistrar
    address public immutable zeroGovernor;

    /// @inheritdoc IRegistrar
    address public immutable zeroToken;

    /// @dev A mapping of keys to values.
    mapping(bytes32 key => bytes32 value) internal _valueAt;

    /* ============ Modifiers ============ */

    /// @dev Revert if the caller is not the Standard Governor nor the Emergency Governor.
    modifier onlyStandardOrEmergencyGovernor() {
        _revertIfNotStandardOrEmergencyGovernor();
        _;
    }

    /* ============ Constructor ============ */

    /**
     * @notice Constructs a new Registrar contract.
     * @param  zeroGovernor_ The address of the ZeroGovernor contract.
     */
    constructor(address zeroGovernor_) {
        if ((zeroGovernor = zeroGovernor_) == address(0)) revert InvalidZeroGovernorAddress();

        IZeroGovernor zeroGovernorInstance_ = IZeroGovernor(zeroGovernor_);

        if ((emergencyGovernorDeployer = zeroGovernorInstance_.emergencyGovernorDeployer()) == address(0))
            revert InvalidEmergencyGovernorDeployerAddress();

        if ((powerTokenDeployer = zeroGovernorInstance_.powerTokenDeployer()) == address(0))
            revert InvalidPowerTokenDeployerAddress();

        address standardGovernorDeployer_ = standardGovernorDeployer = zeroGovernorInstance_.standardGovernorDeployer();

        if (standardGovernorDeployer_ == address(0)) revert InvalidStandardGovernorDeployerAddress();

        if ((zeroToken = zeroGovernorInstance_.voteToken()) == address(0)) revert InvalidVoteTokenAddress();

        if ((vault = IStandardGovernorDeployer(standardGovernorDeployer_).vault()) == address(0))
            revert InvalidVaultAddress();
    }

    /* ============ Interactive Functions ============ */

    /// @inheritdoc IRegistrar
    function addToList(bytes32 list_, address account_) external onlyStandardOrEmergencyGovernor {
        _valueAt[_getIsInListKey(list_, account_)] = bytes32(uint256(1));

        emit AddressAddedToList(list_, account_);
    }

    /// @inheritdoc IRegistrar
    function removeFromList(bytes32 list_, address account_) external onlyStandardOrEmergencyGovernor {
        delete _valueAt[_getIsInListKey(list_, account_)];

        emit AddressRemovedFromList(list_, account_);
    }

    /// @inheritdoc IRegistrar
    function setKey(bytes32 key_, bytes32 value_) external onlyStandardOrEmergencyGovernor {
        emit KeySet(key_, _valueAt[_getValueKey(key_)] = value_);
    }

    /* ============ View/Pure Functions ============ */

    /// @inheritdoc IERC6372
    function clock() external view returns (uint48) {
        return PureEpochs.currentEpoch();
    }

    /// @inheritdoc IRegistrar
    function get(bytes32 key_) external view returns (bytes32) {
        return _valueAt[_getValueKey(key_)];
    }

    /// @inheritdoc IRegistrar
    function get(bytes32[] calldata keys_) external view returns (bytes32[] memory values_) {
        values_ = new bytes32[](keys_.length);

        for (uint256 index_; index_ < keys_.length; ++index_) {
            values_[index_] = _valueAt[_getValueKey(keys_[index_])];
        }
    }

    /// @inheritdoc IRegistrar
    function listContains(bytes32 list_, address account_) external view returns (bool) {
        return _valueAt[_getIsInListKey(list_, account_)] == bytes32(uint256(1));
    }

    /// @inheritdoc IRegistrar
    function listContains(bytes32 list_, address[] calldata accounts_) external view returns (bool) {
        for (uint256 index_; index_ < accounts_.length; ++index_) {
            if (_valueAt[_getIsInListKey(list_, accounts_[index_])] != bytes32(uint256(1))) return false;
        }

        return true;
    }

    /// @inheritdoc IRegistrar
    function powerToken() external view returns (address) {
        return IPowerTokenDeployer(powerTokenDeployer).lastDeploy();
    }

    /// @inheritdoc IERC6372
    function CLOCK_MODE() external pure returns (string memory) {
        return PureEpochs.clockMode();
    }

    /// @inheritdoc IRegistrar
    function clockStartingTimestamp() external pure returns (uint256) {
        return PureEpochs.STARTING_TIMESTAMP;
    }

    /// @inheritdoc IRegistrar
    function clockPeriod() external pure returns (uint256) {
        return PureEpochs.EPOCH_PERIOD;
    }

    /// @inheritdoc IRegistrar
    function emergencyGovernor() public view returns (address) {
        return IEmergencyGovernorDeployer(emergencyGovernorDeployer).lastDeploy();
    }

    /// @inheritdoc IRegistrar
    function standardGovernor() public view returns (address) {
        return IStandardGovernorDeployer(standardGovernorDeployer).lastDeploy();
    }

    /* ============ Internal View/Pure Functions ============ */

    /// @dev Reverts if the caller is not the Standard Governor nor the Emergency Governor.
    function _revertIfNotStandardOrEmergencyGovernor() internal view {
        if (msg.sender != standardGovernor() && msg.sender != emergencyGovernor()) {
            revert NotStandardOrEmergencyGovernor();
        }
    }

    /**
     * @dev    Returns the key used to store the value of `key_`.
     * @param  key_ The key of the value.
     * @return The key used to store the value of `key_`.
     */
    function _getValueKey(bytes32 key_) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("VALUE", key_));
    }

    /**
     * @dev    Returns the key used to store whether `account_` is in `list_`.
     * @param  list_    The list of addresses.
     * @param  account_ The address of the account.
     * @return The key used to store whether `account_` is in `list_`.
     */
    function _getIsInListKey(bytes32 list_, address account_) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("IN_LIST", list_, account_));
    }
}
PureEpochs.sol 34 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

/**
 * @notice Defines epochs as periods away from STARTING_TIMESTAMP timestamp.
 * @author M^0 Labs
 * @dev    Provides a `uint16` epoch clock value.
 */
library PureEpochs {
    /* ============ Variables ============ */

    /// @notice The timestamp of the start of Epoch 1.
    uint40 internal constant STARTING_TIMESTAMP = 1713099600;

    /// @notice The approximate target of seconds an epoch should endure.
    uint40 internal constant EPOCH_PERIOD = 1296000;

    /* ============ Internal View/Pure Functions ============ */

    /// @dev Returns the current epoch number.
    function currentEpoch() internal view returns (uint16) {
        return uint16(((block.timestamp - STARTING_TIMESTAMP) / EPOCH_PERIOD) + 1);
    }

    /// @dev Returns the remaining time in the current epoch.
    function timeRemainingInCurrentEpoch() internal view returns (uint40) {
        return STARTING_TIMESTAMP + (currentEpoch() * EPOCH_PERIOD) - uint40(block.timestamp);
    }

    function clockMode() internal pure returns (string memory) {
        return "mode=epoch&epochUnderlyingSource=blockTimestamp&epochStartingTimestamp=1713099600&epochPeriod=1296000";
    }
}
IDeployer.sol 18 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

/**
 * @title  A Deterministic deployer of contracts using CREATE.
 * @author M^0 Labs
 */
interface IDeployer {
    /// @notice Returns the nonce used to pre deterministically compute the address of the next deployed contract.
    function nonce() external view returns (uint256);

    /// @notice Returns the address of the last contract deployed by this contract.
    function lastDeploy() external view returns (address);

    /// @notice Returns the address of the next contract this contract will deploy.
    function nextDeploy() external view returns (address);
}
IRegistrar.sol 145 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IERC6372 } from "../abstract/interfaces/IERC6372.sol";

/**
 * @title  A book of record of TTG-specific contracts and arbitrary key-value pairs and lists.
 * @author M^0 Labs
 */
interface IRegistrar is IERC6372 {
    /* ============ Events ============ */

    /**
     * @notice Emitted when `account` is added to `list`.
     * @param  list    The key for the list.
     * @param  account The address of the added account.
     */
    event AddressAddedToList(bytes32 indexed list, address indexed account);

    /**
     * @notice Emitted when `account` is removed from `list`.
     * @param  list    The key for the list.
     * @param  account The address of the removed account.
     */
    event AddressRemovedFromList(bytes32 indexed list, address indexed account);

    /**
     * @notice Emitted when `key` is set to `value`.
     * @param  key   The key.
     * @param  value The value.
     */
    event KeySet(bytes32 indexed key, bytes32 indexed value);

    /* ============ Custom Errors ============ */

    /// @notice Revert message when the Emergency Governor Deployer retrieved in the constructor is address(0).
    error InvalidEmergencyGovernorDeployerAddress();

    /// @notice Revert message when the Power Token Deployer retrieved in the constructor is address(0).
    error InvalidPowerTokenDeployerAddress();

    /// @notice Revert message when the Standard Governor Deployer retrieved in the constructor is address(0).
    error InvalidStandardGovernorDeployerAddress();

    /// @notice Revert message when the Vault retrieved in the constructor is address(0).
    error InvalidVaultAddress();

    /// @notice Revert message when the Vote Token retrieved in the constructor is address(0).
    error InvalidVoteTokenAddress();

    /// @notice Revert message when the Zero Governor specified in the constructor is address(0).
    error InvalidZeroGovernorAddress();

    /// @notice Revert message when the caller is not the Standard Governor nor the Emergency Governor.
    error NotStandardOrEmergencyGovernor();

    /* ============ Interactive Functions ============ */

    /**
     * @notice Adds `account` to `list`.
     * @param  list    The key for some list.
     * @param  account The address of some account to be added.
     */
    function addToList(bytes32 list, address account) external;

    /**
     * @notice Removes `account` from `list`.
     * @param  list    The key for some list.
     * @param  account The address of some account to be removed.
     */
    function removeFromList(bytes32 list, address account) external;

    /**
     * @notice Sets `key` to `value`.
     * @param  key   Some key.
     * @param  value Some value.
     */
    function setKey(bytes32 key, bytes32 value) external;

    /* ============ View/Pure Functions ============ */

    /// @notice Returns the starting timestamp of Epoch 1.
    function clockStartingTimestamp() external pure returns (uint256);

    /// @notice Returns the period/duration, in seconds, of an epoch.
    function clockPeriod() external pure returns (uint256);

    /**
     * @notice Returns the value of `key`.
     * @param  key Some key.
     * @return Some value.
     */
    function get(bytes32 key) external view returns (bytes32);

    /**
     * @notice Returns the values of `keys` respectively.
     * @param  keys Some keys.
     * @return Some values.
     */
    function get(bytes32[] calldata keys) external view returns (bytes32[] memory);

    /**
     * @notice Returns whether `list` contains `account`.
     * @param  list    The key for some list.
     * @param  account The address of some account.
     * @return Whether `list` contains `account`.
     */
    function listContains(bytes32 list, address account) external view returns (bool);

    /**
     * @notice Returns whether `list` contains all specified accounts.
     * @param  list     The key for some list.
     * @param  accounts An array of addressed of some accounts.
     * @return Whether `list` contains all specified accounts.
     */
    function listContains(bytes32 list, address[] calldata accounts) external view returns (bool);

    /// @notice Returns the address of the Emergency Governor.
    function emergencyGovernor() external view returns (address);

    /// @notice Returns the address of the Emergency Governor Deployer.
    function emergencyGovernorDeployer() external view returns (address);

    /// @notice Returns the address of the Power Token.
    function powerToken() external view returns (address);

    /// @notice Returns the address of the Power Token Deployer.
    function powerTokenDeployer() external view returns (address);

    /// @notice Returns the address of the Standard Governor.
    function standardGovernor() external view returns (address);

    /// @notice Returns the address of the Standard Governor Deployer.
    function standardGovernorDeployer() external view returns (address);

    /// @notice Returns the address of the Vault.
    function vault() external view returns (address);

    /// @notice Returns the address of the Zero Governor.
    function zeroGovernor() external view returns (address);

    /// @notice Returns the address of the Zero Token.
    function zeroToken() external view returns (address);
}
IZeroGovernor.sol 127 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IThresholdGovernor } from "../abstract/interfaces/IThresholdGovernor.sol";

/**
 * @title  An instance of a ThresholdGovernor with a unique and limited set of possible proposals.
 * @author M^0 Labs
 */
interface IZeroGovernor is IThresholdGovernor {
    /* ============ Events ============ */

    /**
     * @notice Emitted upon contract deployment, once the set of allowed cash tokens is finalized.
     * @param  allowedCashTokens An array of addressed that are allowed as cash tokens.
     */
    event AllowedCashTokensSet(address[] allowedCashTokens);

    /**
     * @notice Emitted upon a Reset, resulting in a new Standard Governor, Emergency Governor, and Power Token.
     * @param  bootstrapToken    The address of token (Zero Token or old Power Token), that bootstraps the reset.
     * @param  standardGovernor  The address of the new Standard Governor.
     * @param  emergencyGovernor The address of the new Emergency Governor.
     * @param  powerToken        The address of the new Power Token.
     */
    event ResetExecuted(
        address indexed bootstrapToken,
        address standardGovernor,
        address emergencyGovernor,
        address powerToken
    );

    /* ============ Custom Errors ============ */

    /// @notice Revert message when the Cash Token specified is not in the allowed set.
    error InvalidCashToken();

    /// @notice Revert message when the Cash Token specified in the constructor is address(0).
    error InvalidCashTokenAddress();

    /// @notice Revert message when the Emergency Governor Deployer specified in the constructor is address(0).
    error InvalidEmergencyGovernorDeployerAddress();

    /// @notice Revert message when the Power Token Deployer specified in the constructor is address(0).
    error InvalidPowerTokenDeployerAddress();

    /// @notice Revert message when the Standard Governor Deployer specified in the constructor is address(0).
    error InvalidStandardGovernorDeployerAddress();

    /// @notice Revert message when the set of allowed cash tokens specified in the constructor is empty.
    error NoAllowedCashTokens();

    /**
     * @notice Revert message when the address of the deployed Power Token differs fro what was expected.
     * @param  expected The expected address of the deployed Power Token.
     * @param  deployed The actual address of the deployed Power Token.
     */
    error UnexpectedPowerTokenDeployed(address expected, address deployed);

    /**
     * @notice Revert message when the address of the deployed Standard Governor differs fro what was expected.
     * @param  expected The expected address of the deployed Standard Governor.
     * @param  deployed The actual address of the deployed Standard Governor.
     */
    error UnexpectedStandardGovernorDeployed(address expected, address deployed);

    /* ============ Proposal Functions ============ */

    /**
     * @notice One of the valid proposals. Reset the Standard Governor, Emergency Governor, and Power Token to the
     *         Power Token holders. This would be used by Zero Token holders in the event that inflation is soon to
     *         result in Power Token overflowing, and/or there is a loss of faith in the state of either the Standard
     *         Governor or Emergency Governor.
     */
    function resetToPowerHolders() external;

    /**
     * @notice One of the valid proposals. Reset the Standard Governor, Emergency Governor, and Power Token to the
     *         ZeroToken holders. This would be used by Zero Token holders if they no longer have faith in the current
     *         set of PowerToken holders and/or the state of either the Standard Governor or Emergency Governor.
     */
    function resetToZeroHolders() external;

    /**
     * @notice One of the valid proposals. Sets the Cash Token of the system.
     * @param  newCashToken   The address of the new cash token.
     * @param  newProposalFee The amount of cash token required onwards to create Standard Governor proposals.
     */
    function setCashToken(address newCashToken, uint256 newProposalFee) external;

    /**
     * @notice One of the valid proposals. Sets the threshold ratio for Emergency Governor proposals.
     * @param  newThresholdRatio The new threshold ratio.
     */
    function setEmergencyProposalThresholdRatio(uint16 newThresholdRatio) external;

    /**
     * @notice One of the valid proposals. Sets the threshold ratio for this governor's proposals.
     * @param  newThresholdRatio The new threshold ratio.
     */
    function setZeroProposalThresholdRatio(uint16 newThresholdRatio) external;

    /* ============ View/Pure Functions ============ */

    /**
     * @notice Returns whether `token` is an allowed Cash Token of the system, as a parameter in setCashToken proposal.
     * @param  token The address of some token.
     * @return Whether `token` is an allowed Cash Token.
     */
    function isAllowedCashToken(address token) external view returns (bool);

    /// @notice Returns the address of the Emergency Governor.
    function emergencyGovernor() external view returns (address);

    /// @notice Returns the address of the Emergency Governor Deployer.
    function emergencyGovernorDeployer() external view returns (address);

    /// @notice Returns the address of the Power Token Deployer.
    function powerTokenDeployer() external view returns (address);

    /// @notice Returns the address of the Standard Governor.
    function standardGovernor() external view returns (address);

    /// @notice Returns the address of the Standard Governor Deployer.
    function standardGovernorDeployer() external view returns (address);
}
IERC6372.sol 16 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

/**
 * @title  Contract clock properties.
 * @author M^0 Labs
 * @dev    The interface as defined by EIP-6372: https://eips.ethereum.org/EIPS/eip-6372
 */
interface IERC6372 {
    /// @notice Returns a machine-readable string description of the clock the contract is operating on.
    function CLOCK_MODE() external view returns (string memory);

    /// @notice Returns the current timepoint according to the mode the contract is operating on.
    function clock() external view returns (uint48);
}
IERC712.sol 39 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

/**
 * @title  Typed structured data hashing and signing via EIP-712.
 * @author M^0 Labs
 * @dev    The interface as defined by EIP-712: https://eips.ethereum.org/EIPS/eip-712
 */
interface IERC712 {
    /* ============ Custom Errors ============ */

    /// @notice Revert message when an invalid signature is detected.
    error InvalidSignature();

    /// @notice Revert message when a signature with invalid length is detected.
    error InvalidSignatureLength();

    /// @notice Revert message when the S portion of a signature is invalid.
    error InvalidSignatureS();

    /// @notice Revert message when the V portion of a signature is invalid.
    error InvalidSignatureV();

    /**
     * @notice Revert message when a signature is being used beyond its deadline (i.e. expiry).
     * @param  deadline  The deadline of the signature.
     * @param  timestamp The current timestamp.
     */
    error SignatureExpired(uint256 deadline, uint256 timestamp);

    /// @notice Revert message when a recovered signer does not match the account being purported to have signed.
    error SignerMismatch();

    /* ============ View/Pure Functions ============ */

    /// @notice Returns the EIP712 domain separator used in the encoding of a signed digest.
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}
IGovernor.sol 306 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IERC712 } from "../../../lib/common/src/interfaces/IERC712.sol";

import { IERC6372 } from "./IERC6372.sol";

/**
 * @title  Minimal OpenZeppelin-style, Tally-compatible governor.
 * @author M^0 Labs
 */
interface IGovernor is IERC6372, IERC712 {
    /* ============ Enums ============ */

    /**
     * @notice Proposal state.
     * @param  Pending   The proposal has been created, but the vote has not started yet.
     * @param  Active    The proposal is currently in the voting period.
     * @param  Canceled  The proposal has been canceled.
     * @param  Defeated  The proposal has been defeated.
     * @param  Succeeded The proposal has succeeded.
     * @param  Queued    The proposal has been queued.
     * @param  Expired   The proposal has expired.
     * @param  Executed  The proposal has been executed.
     */
    enum ProposalState {
        Pending,
        Active,
        Canceled, // never used by TTG.
        Defeated,
        Succeeded,
        Queued, // never used by TTG.
        Expired,
        Executed
    }

    /* ============ Events ============ */

    /**
     * @notice Emitted when a proposal has been created.
     * @param  proposalId  The unique identifier for the proposal.
     * @param  proposer    The address of the account that created the proposal.
     * @param  targets     An array of addresses that will be called upon the execution.
     * @param  values      An array of ETH amounts that will be sent to each respective target upon execution.
     * @param  signatures  Empty string array required to be compatible with OZ governor contract.
     * @param  callDatas   An array of call data used to call each respective target upon execution.
     * @param  voteStart   The first clock value when voting on the proposal is allowed.
     * @param  voteEnd     The last clock value when voting on the proposal is allowed.
     * @param  description The string of the description of the proposal.
     */
    event ProposalCreated(
        uint256 proposalId,
        address proposer,
        address[] targets,
        uint256[] values,
        string[] signatures,
        bytes[] callDatas,
        uint256 voteStart,
        uint256 voteEnd,
        string description
    );

    /**
     * @notice Emitted when a proposal has been executed.
     * @param  proposalId The unique identifier for the proposal.
     */
    event ProposalExecuted(uint256 proposalId);

    /**
     * @notice Emitted when a vote for a proposal with id `proposalId` has been cast by `voter`.
     * @param  voter      The address of the account that has casted their vote.
     * @param  proposalId The unique identifier for the proposal.
     * @param  support    The type of support that has been cast for the proposal.
     * @param  weight     The number of votes cast.
     * @param  reason     The string of the reason `voter` has cast their vote, if any.
     */
    event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);

    /* ============ Interactive Functions ============ */

    /**
     * @notice Allows the caller to cast a vote on a proposal with id `proposalId`.
     * @param  proposalId The unique identifier for the proposal.
     * @param  support    The type of support to cast for the proposal.
     * @return weight     The number of votes cast.
     */
    function castVote(uint256 proposalId, uint8 support) external returns (uint256 weight);

    /**
     * @notice Allows a signer to cast a vote on a proposal with id `proposalId` via an ECDSA secp256k1 signature.
     * @param  proposalId The unique identifier for the proposal.
     * @param  support    The type of support to cast for the proposal.
     * @param  v          An ECDSA secp256k1 signature parameter.
     * @param  r          An ECDSA secp256k1 signature parameter.
     * @param  s          An ECDSA secp256k1 signature parameter.
     * @return weight     The number of votes cast.
     */
    function castVoteBySig(
        uint256 proposalId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 weight);

    /**
     * @notice Allows `voter` to cast a vote on a proposal with id `proposalId` via an arbitrary signature.
     * @param  voter      The address of the account that casting their vote, and purported to have signed.
     * @param  proposalId The unique identifier for the proposal.
     * @param  support    The type of support to cast for the proposal.
     * @param  signature  An arbitrary signature.
     * @return weight     The number of votes cast.
     */
    function castVoteBySig(
        address voter,
        uint256 proposalId,
        uint8 support,
        bytes memory signature
    ) external returns (uint256 weight);

    /**
     * @notice Allows the caller to cast a vote with reason on a proposal with id `proposalId`.
     * @param  proposalId The unique identifier for the proposal.
     * @param  support    The type of support to cast for the proposal.
     * @param  reason     The reason for which the caller casts their vote, if any.
     * @return weight     The number of votes cast.
     */
    function castVoteWithReason(
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) external returns (uint256 weight);

    /**
     * @notice Allows a signer to cast a vote with reason on a proposal with id `proposalId`
     *         via an ECDSA secp256k1 signature.
     * @param  proposalId The unique identifier for the proposal.
     * @param  support    The type of support to cast for the proposal.
     * @param  reason     The reason for which the caller casts their vote, if any.
     * @param  v          An ECDSA secp256k1 signature parameter.
     * @param  r          An ECDSA secp256k1 signature parameter.
     * @param  s          An ECDSA secp256k1 signature parameter.
     * @return weight     The number of votes cast.
     */
    function castVoteWithReasonBySig(
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 weight);

    /**
     * @notice Allows `voter` to cast a vote with reason on a proposal with id `proposalId` via an arbitrary signature.
     * @param  voter      The address of the account that casting their vote, and purported to have signed.
     * @param  proposalId The unique identifier for the proposal.
     * @param  support    The type of support to cast for the proposal.
     * @param  reason     The reason for which the caller casts their vote, if any.
     * @param  signature  An arbitrary signature.
     * @return weight     The number of votes cast.
     */
    function castVoteWithReasonBySig(
        address voter,
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        bytes memory signature
    ) external returns (uint256 weight);

    /**
     * @notice Allows the caller to execute a proposal.
     * @param  targets         An array of addresses that will be called upon the execution.
     * @param  values          An array of ETH amounts that will be sent to each respective target upon execution.
     * @param  callDatas       An array of call data used to call each respective target upon execution.
     * @param  descriptionHash The hash of the string of the description of the proposal.
     * @return proposalId      The unique identifier for the proposal.
     */
    function execute(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory callDatas,
        bytes32 descriptionHash
    ) external payable returns (uint256 proposalId);

    /**
     * @notice Allows the caller to create a proposal.
     * @param  targets     An array of addresses that will be called upon the execution.
     * @param  values      An array of ETH amounts that will be sent to each respective target upon execution.
     * @param  callDatas   An array of call data used to call each respective target upon execution.
     * @param  description The string of the description of the proposal.
     * @return proposalId  The unique identifier for the proposal.
     */
    function propose(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory callDatas,
        string memory description
    ) external returns (uint256 proposalId);

    /* ============ View/Pure Functions ============ */

    /**
     * @notice module:voting
     * @dev    A description of the possible "support" values for castVote and the way these votes are counted, meant to
     *         be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded
     *         sequence of key-value pairs that each describe one aspect, for example `support=for,against&quorum=for`.
     *         The string can be decoded by the standard URLSearchParams JavaScript class.
     */
    function COUNTING_MODE() external view returns (string memory);

    /**
     * @notice Returns the voting power of `account` at clock value `timepoint`.
     * @param  account   The address of the account with voting power.
     * @param  timepoint The point in time, according to the clock mode the contract is operating on.
     * @return The voting power of `account` at `timepoint`.
     */
    function getVotes(address account, uint256 timepoint) external view returns (uint256);

    /**
     * @notice Returns the unique identifier for the proposal if it were created at this exact moment.
     * @param  targets         An array of addresses that will be called upon the execution.
     * @param  values          An array of ETH amounts that will be sent to each respective target upon execution.
     * @param  callDatas       An array of call data used to call each respective target upon execution.
     * @param  descriptionHash The hash of the string of the description of the proposal.
     * @return The unique identifier for the proposal.
     */
    function hashProposal(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory callDatas,
        bytes32 descriptionHash
    ) external view returns (uint256);

    /**
     * @notice Returns whether `account` has voted on the proposal with identifier `proposalId`.
     * @param  proposalId The unique identifier for the proposal.
     * @param  account    The address of some account.
     * @return Whether `account` has already voted on the proposal.
     */
    function hasVoted(uint256 proposalId, address account) external view returns (bool);

    /// @notice Returns the name of the contract.
    function name() external view returns (string memory);

    /**
     * @notice Returns the last clock value when voting on the proposal with identifier `proposalId` is allowed.
     * @param  proposalId The unique identifier for the proposal.
     * @return The last clock value when voting on the proposal is allowed.
     */
    function proposalDeadline(uint256 proposalId) external view returns (uint256);

    /**
     * @notice Returns the account that created the proposal with identifier `proposalId`.
     * @param  proposalId The unique identifier for the proposal.
     * @return The address of the account that created the proposal.
     */
    function proposalProposer(uint256 proposalId) external view returns (address);

    /**
     * @notice Returns the clock value used to retrieve voting power to vote on proposal with identifier `proposalId`.
     * @param  proposalId The unique identifier for the proposal.
     * @return The clock value used to retrieve voting power.
     */
    function proposalSnapshot(uint256 proposalId) external view returns (uint256);

    /// @notice Returns the required voting power an account needs to create a proposal.
    function proposalThreshold() external view returns (uint256);

    /**
     * @notice Returns the vote support totals for the proposal with identifier `proposalId`.
     * @param  proposalId   The unique identifier for the proposal.
     * @return noVotes      The amount of votes cast against the proposal.
     * @return yesVotes     The amount of votes cast for the proposal.
     * @return abstainVotes The amount of votes cast in abstention the proposal.
     */
    function proposalVotes(
        uint256 proposalId
    ) external view returns (uint256 noVotes, uint256 yesVotes, uint256 abstainVotes);

    /// @notice Returns the minimum number of eligible (COUNTING_MODE) votes for a proposal to succeed.
    function quorum() external view returns (uint256);

    /**
     * @notice Returns the state of a proposal with identifier `proposalId`.
     * @param  proposalId The unique identifier for the proposal.
     * @return The state of the proposal.
     */
    function state(uint256 proposalId) external view returns (ProposalState);

    /// @notice Returns the EIP-5805 token contact used for determine voting power and total supplies.
    function token() external view returns (address);

    /// @notice Returns the number of clock values that must elapse before voting begins for a newly created proposal.
    function votingDelay() external view returns (uint256);

    /// @notice Returns the number of clock values between the vote start and vote end.
    function votingPeriod() external view returns (uint256);

    /// @notice Returns the EIP712 typehash used in the encoding of the digest for `castVoteBySig` function.
    function BALLOT_TYPEHASH() external pure returns (bytes32);

    /// @notice Returns the EIP712 typehash used in the encoding of the digest for `castVoteWithReasonBySig` function.
    function BALLOT_WITH_REASON_TYPEHASH() external pure returns (bytes32);
}
IPowerTokenDeployer.sol 42 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IDeployer } from "./IDeployer.sol";

/**
 * @title  A Deterministic deployer of Power Token contracts using CREATE.
 * @author M^0 Labs
 */
interface IPowerTokenDeployer is IDeployer {
    /* ============ Custom Errors ============ */

    /// @notice Revert message when the Vault specified in the constructor is address(0).
    error InvalidVaultAddress();

    /// @notice Revert message when the Zero Governor specified in the constructor is address(0).
    error InvalidZeroGovernorAddress();

    /// @notice Revert message when the caller is not the Zero Governor.
    error NotZeroGovernor();

    /* ============ Interactive Functions ============ */

    /**
     * @notice Deploys a new instance of a Power Token.
     * @dev    Callable only by the Zero Governor.
     * @param  bootstrapToken   The address of some token to bootstrap from.
     * @param  standardGovernor The address of some Standard Governor.
     * @param  cashToken        The address of some Cash Token.
     * @return The address of the deployed Emergency Governor.
     */
    function deploy(address bootstrapToken, address standardGovernor, address cashToken) external returns (address);

    /* ============ View/Pure Functions ============ */

    /// @notice Returns the address of the Vault.
    function vault() external view returns (address);

    /// @notice Returns the address of the Zero Governor.
    function zeroGovernor() external view returns (address);
}
IBatchGovernor.sol 241 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IGovernor } from "./IGovernor.sol";

/**
 * @title  Extension for Governor with specialized strict proposal parameters, vote batching, and an epoch clock.
 * @author M^0 Labs
 */
interface IBatchGovernor is IGovernor {
    /* ============ Enums ============ */

    /**
     * @notice The type of support to cast for a proposal.
     * @param  No  The voter does not support the proposal.
     * @param  Yes The voter supports the proposal.
     */
    enum VoteType {
        No,
        Yes
    }

    /* ============ Custom Errors ============ */

    /// @notice Revert message when a voter is trying to vote on a proposal they already voted on.
    error AlreadyVoted();

    /// @notice Revert message when input arrays do not match in length.
    error ArrayLengthMismatch(uint256 length1, uint256 length2);

    /// @notice Revert message when the proposal IDs array is empty.
    error EmptyProposalIdsArray();

    /**
     * @notice Revert message when execution of a proposal fails.
     * @param  data The revert data returned due to the failed execution.
     */
    error ExecutionFailed(bytes data);

    /// @notice Revert message when a proposal's call data is not specifically supported.
    error InvalidCallData();

    /// @notice Revert message when a proposal's call data array is not of length 1.
    error InvalidCallDatasLength();

    /// @notice Revert message when a proposal target is not this governor itself.
    error InvalidTarget();

    /// @notice Revert message when a proposal's targets array is not of length 1.
    error InvalidTargetsLength();

    /// @notice Revert message when a proposal value is not 0 ETH.
    error InvalidValue();

    /// @notice Revert message when a proposal's values array is not of length 1.
    error InvalidValuesLength();

    /// @notice Revert message when a an invalid vote start is detected.
    error InvalidVoteStart();

    /// @notice Revert message when the vote token specified in the constructor is address(0).
    error InvalidVoteTokenAddress();

    /// @notice Revert message when the caller of a governance-controlled function is not this governor itself.
    error NotSelf();

    /// @notice Revert message when the proposal information provided cannot be executed.
    error ProposalCannotBeExecuted();

    /// @notice Revert message when the proposal does not exist.
    error ProposalDoesNotExist();

    /// @notice Revert message when the proposal already exists.
    error ProposalExists();

    /**
     * @notice Revert message when voting on a proposal that is not in an active state (i.e. not collecting votes).
     * @param  state The current state of the proposal.
     */
    error ProposalInactive(ProposalState state);

    /// @notice Revert message when voting on a proposal with a zero voting weight.
    error ZeroVotingPower();

    /* ============ Interactive Functions ============ */

    /**
     * @notice Allows the caller to cast votes on multiple proposals.
     * @param  proposalIds The list of unique proposal IDs being voted on.
     * @param  supportList The list of support type per proposal IDs to cast.
     * @return weight      The number of votes cast for each proposal (the same for all of them).
     */
    function castVotes(uint256[] calldata proposalIds, uint8[] calldata supportList) external returns (uint256 weight);

    /**
     * @notice Allows a signer to cast votes on multiple proposals via an ECDSA secp256k1 signature.
     * @param  proposalIds The list of unique proposal IDs being voted on.
     * @param  supportList The list of support type per proposal IDs to cast.
     * @param  v           An ECDSA secp256k1 signature parameter.
     * @param  r           An ECDSA secp256k1 signature parameter.
     * @param  s           An ECDSA secp256k1 signature parameter.
     * @return weight      The number of votes cast for each proposal (the same for all of them).
     */
    function castVotesBySig(
        uint256[] calldata proposalIds,
        uint8[] calldata supportList,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 weight);

    /**
     * @notice Allows a signer to cast votes on multiple proposals via an arbitrary signature.
     * @param  voter       The address of the account casting the votes.
     * @param  proposalIds The list of unique proposal IDs being voted on.
     * @param  supportList The list of support type per proposal IDs to cast.
     * @param  signature   An arbitrary signature
     * @return weight      The number of votes cast for each proposal (the same for all of them).
     */
    function castVotesBySig(
        address voter,
        uint256[] calldata proposalIds,
        uint8[] calldata supportList,
        bytes memory signature
    ) external returns (uint256 weight);

    /**
     * @notice Allows the caller to cast votes with reason on multiple proposals.
     * @param  proposalIds The list of unique proposal IDs being voted on.
     * @param  supportList The list of support type per proposal IDs to cast.
     * @param  reasonList  The list of reason per proposal IDs to cast.
     * @return weight      The number of votes cast for each proposal (the same for all of them).
     */
    function castVotesWithReason(
        uint256[] calldata proposalIds,
        uint8[] calldata supportList,
        string[] calldata reasonList
    ) external returns (uint256 weight);

    /**
     * @notice Allows a signer to cast votes with reason on multiple proposals via an ECDSA secp256k1 signature.
     * @param  proposalIds The list of unique proposal IDs being voted on.
     * @param  supportList The list of support type per proposal IDs to cast.
     * @param  reasonList  The list of reason per proposal IDs to cast.
     * @param  v           An ECDSA secp256k1 signature parameter.
     * @param  r           An ECDSA secp256k1 signature parameter.
     * @param  s           An ECDSA secp256k1 signature parameter.
     * @return weight      The number of votes cast for each proposal (the same for all of them).
     */
    function castVotesWithReasonBySig(
        uint256[] calldata proposalIds,
        uint8[] calldata supportList,
        string[] calldata reasonList,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 weight);

    /**
     * @notice Allows a signer to cast votes with reason on multiple proposals via an arbitrary signature.
     * @param  voter       The address of the account casting the votes.
     * @param  proposalIds The list of unique proposal IDs being voted on.
     * @param  supportList The list of support type per proposal IDs to cast.
     * @param  reasonList  The list of reason per proposal IDs to cast.
     * @param  signature   An arbitrary signature
     * @return weight      The number of votes cast for each proposal (the same for all of them).
     */
    function castVotesWithReasonBySig(
        address voter,
        uint256[] calldata proposalIds,
        uint8[] calldata supportList,
        string[] calldata reasonList,
        bytes memory signature
    ) external returns (uint256 weight);

    /* ============ View/Pure Functions ============ */

    /**
     * @notice Returns the ballot digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).
     * @param  proposalId The unique proposal ID being voted on.
     * @param  support    The type of support to cast for the proposal.
     * @return The digest to be signed.
     */
    function getBallotDigest(uint256 proposalId, uint8 support) external view returns (bytes32);

    /**
     * @notice Returns the ballots digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).
     * @param  proposalIds The list of unique proposal IDs being voted on.
     * @param  supportList The list of support type per proposal IDs to cast.
     * @return The digest to be signed.
     */
    function getBallotsDigest(
        uint256[] calldata proposalIds,
        uint8[] calldata supportList
    ) external view returns (bytes32);

    /**
     * @notice Returns the ballot with reason digest to be signed, via EIP-712,
     *         given an internal digest (i.e. hash struct).
     * @param  proposalId The unique proposal ID being voted on.
     * @param  support    The type of support to cast for the proposal.
     * @param  reason     The reason for which the caller casts their vote, if any.
     * @return The digest to be signed.
     */
    function getBallotWithReasonDigest(
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) external view returns (bytes32);

    /**
     * @notice Returns the ballots with reason digest to be signed, via EIP-712,
     *         given an internal digest (i.e. hash struct).
     * @param  proposalIds The list of unique proposal IDs being voted on.
     * @param  supportList The list of support type per proposal IDs to cast.
     * @param  reasonList  The list of reason per proposal IDs to cast.
     * @return The digest to be signed.
     */
    function getBallotsWithReasonDigest(
        uint256[] calldata proposalIds,
        uint8[] calldata supportList,
        string[] calldata reasonList
    ) external view returns (bytes32);

    /**
     * @notice Returns the unique identifier for the proposal if it were created at this exact moment.
     * @param  callData The single call data used to call this governor upon execution of a proposal.
     * @return The unique identifier for the proposal.
     */
    function hashProposal(bytes memory callData) external view returns (uint256);

    /// @notice Returns the EIP-5805 token contact used for determine voting power and total supplies.
    function voteToken() external view returns (address);

    /// @notice Returns the EIP712 typehash used in the encoding of the digest for `castVotesBySig` function.
    function BALLOTS_TYPEHASH() external pure returns (bytes32);

    /// @notice Returns the EIP712 typehash used in the encoding of the digest for `castVotesWithReasonBySig` function.
    function BALLOTS_WITH_REASON_TYPEHASH() external pure returns (bytes32);
}
IStandardGovernorDeployer.sol 61 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IDeployer } from "./IDeployer.sol";

/**
 * @title  A Deterministic deployer of Standard Governor contracts using CREATE.
 * @author M^0 Labs
 */
interface IStandardGovernorDeployer is IDeployer {
    /* ============ Custom Errors ============ */

    /// @notice Revert message when the Registrar specified in the constructor is address(0).
    error InvalidRegistrarAddress();

    /// @notice Revert message when the Vault specified in the constructor is address(0).
    error InvalidVaultAddress();

    /// @notice Revert message when the Zero Governor specified in the constructor is address(0).
    error InvalidZeroGovernorAddress();

    /// @notice Revert message when the Zero Token specified in the constructor is address(0).
    error InvalidZeroTokenAddress();

    /// @notice Revert message when the caller is not the Zero Governor.
    error NotZeroGovernor();

    /* ============ Interactive Functions ============ */

    /**
     * @notice Deploys a new instance of a Standard Governor.
     * @param  powerToken                       The address of some Power Token that will be used by voters.
     * @param  emergencyGovernor                The address of some Emergency Governor.
     * @param  cashToken                        The address of some Cash Token.
     * @param  proposalFee                      The proposal fee required to create proposals.
     * @param  maxTotalZeroRewardPerActiveEpoch The maximum amount of Zero Token rewarded per active epoch.
     * @return The address of the deployed Standard Governor.
     */
    function deploy(
        address powerToken,
        address emergencyGovernor,
        address cashToken,
        uint256 proposalFee,
        uint256 maxTotalZeroRewardPerActiveEpoch
    ) external returns (address);

    /* ============ View/Pure Functions ============ */

    /// @notice Returns the address of the Registrar.
    function registrar() external view returns (address);

    /// @notice Returns the address of the Vault.
    function vault() external view returns (address);

    /// @notice Returns the address of the Zero Governor.
    function zeroGovernor() external view returns (address);

    /// @notice Returns the address of the Zero Token.
    function zeroToken() external view returns (address);
}
IEmergencyGovernorDeployer.sol 41 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IDeployer } from "./IDeployer.sol";

/**
 * @title  A Deterministic deployer of Emergency Governor contracts using CREATE.
 * @author M^0 Labs
 */
interface IEmergencyGovernorDeployer is IDeployer {
    /* ============ Custom Errors ============ */

    /// @notice Revert message when the Registrar specified in the constructor is address(0).
    error InvalidRegistrarAddress();

    /// @notice Revert message when the Zero Governor specified in the constructor is address(0).
    error InvalidZeroGovernorAddress();

    /// @notice Revert message when the caller is not the Zero Governor.
    error NotZeroGovernor();

    /* ============ Interactive Functions ============ */

    /**
     * @notice Deploys a new instance of an Emergency Governor.
     * @param  powerToken       The address of some Power Token that will be used by voters.
     * @param  standardGovernor The address of some Standard Governor.
     * @param  thresholdRatio   The threshold ratio to use for proposals.
     * @return The address of the deployed Emergency Governor.
     */
    function deploy(address powerToken, address standardGovernor, uint16 thresholdRatio) external returns (address);

    /* ============ View/Pure Functions ============ */

    /// @notice Returns the address of the Registrar.
    function registrar() external view returns (address);

    /// @notice Returns the address of the Zero Governor.
    function zeroGovernor() external view returns (address);
}
IThresholdGovernor.sol 91 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.23;

import { IBatchGovernor } from "./IBatchGovernor.sol";

/**
 * @title  Extension for BatchGovernor with a threshold ratio used to determine quorum and yes-threshold requirements.
 * @author M^0 Labs
 */
interface IThresholdGovernor is IBatchGovernor {
    /* ============ Events ============ */

    /**
     * @notice Emitted when the threshold ratio is set.
     * @param  thresholdRatio The new threshold ratio.
     */
    event ThresholdRatioSet(uint16 thresholdRatio);

    /**
     * @notice Emitted when the quorum numerator is set.
     * @param  oldQuorumNumerator The old quorum numerator.
     * @param  newQuorumNumerator The new quorum numerator.
     */
    event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);

    /* ============ Custom Errors ============ */

    /**
     * @notice Revert message when trying to set the threshold ratio above 100% or below 2.71%.
     * @param  thresholdRatio    The threshold ratio being set.
     * @param  minThresholdRatio The minimum allowed threshold ratio.
     * @param  maxThresholdRatio The maximum allowed threshold ratio.
     */
    error InvalidThresholdRatio(uint256 thresholdRatio, uint256 minThresholdRatio, uint256 maxThresholdRatio);

    /* ============ View/Pure Functions ============ */

    /**
     * @notice Returns all data of a proposal with identifier `proposalId`.
     * @param  proposalId      The unique identifier for the proposal.
     * @return voteStart       The first clock value when voting on the proposal is allowed.
     * @return voteEnd         The last clock value when voting on the proposal is allowed.
     * @return state           The state of the proposal.
     * @return noVotes         The amount of votes cast against the proposal.
     * @return yesVotes        The amount of votes cast for the proposal.
     * @return proposer        The address of the account that created the proposal.
     * @return quorum          The threshold/quorum of yes votes required for the proposal to succeed.
     * @return quorumNumerator The threshold/quorum numerator used to calculate the quorum.
     */
    function getProposal(
        uint256 proposalId
    )
        external
        view
        returns (
            uint48 voteStart,
            uint48 voteEnd,
            ProposalState state,
            uint256 noVotes,
            uint256 yesVotes,
            address proposer,
            uint256 quorum,
            uint16 quorumNumerator
        );

    /**
     * @notice Returns the threshold ratio to be applied to determine the success threshold for a proposal.
     * @dev    For all intents and purposes, this is the same as `quorumNumerator`.
     */
    function thresholdRatio() external view returns (uint16);

    /**
     * @notice Returns the quorum of yes votes needed for a specific proposal to succeed.
     * @param  proposalId The unique identifier for the proposal.
     * @return The quorum of yes votes needed for the proposal to succeed.
     */
    function proposalQuorum(uint256 proposalId) external view returns (uint256);

    /**
     * @notice Returns the quorum numerator used to determine the quorum for a proposal.
     * @dev    For all intents and purposes, this is the same as `thresholdRatio`.
     */
    function quorumNumerator() external view returns (uint256);

    /// @notice Returns the quorum denominator used to determine the quorum for a proposal.
    function quorumDenominator() external view returns (uint256);

    /// @notice Returns the value used as 100%, to be used to correctly ascertain the threshold ratio.
    function ONE() external pure returns (uint256);
}

Read Contract

CLOCK_MODE 0x4bf5d7e9 → string
clock 0x91ddadf4 → uint48
clockPeriod 0x246c5308 → uint256
clockStartingTimestamp 0xb3d0c202 → uint256
emergencyGovernor 0xf52c93c5 → address
emergencyGovernorDeployer 0x5548917f → address
get 0x8eaa6ac0 → bytes32
get 0xabf306a8 → bytes32[]
listContains 0x2595f8cf → bool
listContains 0xd7d1c1c0 → bool
powerToken 0x9662ac58 → address
powerTokenDeployer 0xaf63a3e1 → address
standardGovernor 0x4d6d7441 → address
standardGovernorDeployer 0xe94bb223 → address
vault 0xfbfa77cf → address
zeroGovernor 0x8df3227f → address
zeroToken 0xf294bd92 → address

Write Contract 3 functions

These functions modify contract state and require a wallet transaction to execute.

addToList 0xb4d87a12
bytes32 list_
address account_
removeFromList 0xd48d8423
bytes32 list_
address account_
setKey 0x07a00330
bytes32 key_
bytes32 value_

Recent Transactions

This address has 1 on-chain transactions, but only <1% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →