creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "lib/ttg/src/StandardGovernor.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { ERC20Helper } from \"../lib/erc20-helper/src/ERC20Helper.sol\";\n\nimport { IGovernor } from \"./abstract/interfaces/IGovernor.sol\";\n\nimport { BatchGovernor } from \"./abstract/BatchGovernor.sol\";\n\nimport { IPowerToken } from \"./interfaces/IPowerToken.sol\";\nimport { IRegistrar } from \"./interfaces/IRegistrar.sol\";\nimport { IStandardGovernor } from \"./interfaces/IStandardGovernor.sol\";\nimport { IZeroToken } from \"./interfaces/IZeroToken.sol\";\n\n/**\n * @title  An instance of a BatchGovernor with a unique and limited set of possible proposals with proposal fees.\n * @author M^0 Labs\n */\ncontract StandardGovernor is IStandardGovernor, BatchGovernor {\n    /* ============ Structs ============ */\n\n    /**\n     * @notice The proposal fee info.\n     * @param  cashToken The address of the cash token used to pay the fee.\n     * @param  fee       The amount of the fee per proposal.\n     */\n    struct ProposalFeeInfo {\n        address cashToken;\n        uint256 fee;\n    }\n\n    /* ============ Variables ============ */\n\n    /// @inheritdoc IStandardGovernor\n    address public immutable emergencyGovernor;\n\n    /// @inheritdoc IStandardGovernor\n    address public immutable registrar;\n\n    /// @inheritdoc IStandardGovernor\n    address public immutable vault;\n\n    /// @inheritdoc IStandardGovernor\n    address public immutable zeroGovernor;\n\n    /// @inheritdoc IStandardGovernor\n    address public immutable zeroToken;\n\n    /// @inheritdoc IStandardGovernor\n    uint256 public immutable maxTotalZeroRewardPerActiveEpoch;\n\n    /// @inheritdoc IStandardGovernor\n    address public cashToken;\n\n    /// @inheritdoc IStandardGovernor\n    uint256 public proposalFee;\n\n    /// @dev The proposal fee info per proposal ID.\n    mapping(uint256 proposalId => ProposalFeeInfo proposalFee) internal _proposalFees;\n\n    /// @dev The amount of proposals per epoch.\n    mapping(uint256 epoch => uint256 count) public numberOfProposalsAt;\n\n    /// @dev The amount of proposals a voter has voted on per epoch.\n    mapping(address voter => mapping(uint256 epoch => uint256 count)) public numberOfProposalsVotedOnAt;\n\n    /* ============ Modifiers ============ */\n\n    /// @dev Revert if the caller is not the Zero Governor.\n    modifier onlyZeroGovernor() {\n        if (msg.sender != zeroGovernor) revert NotZeroGovernor();\n        _;\n    }\n\n    /// @dev Revert if the caller is not the Standard Governor nor the Emergency Governor.\n    modifier onlySelfOrEmergencyGovernor() {\n        if (msg.sender != address(this) && msg.sender != emergencyGovernor) revert NotSelfOrEmergencyGovernor();\n        _;\n    }\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Constructs a new StandardGovernor contract.\n     * @param  voteToken_                        The address of the Vote Token contract.\n     * @param  emergencyGovernor_                The address of the Emergency Governor contract.\n     * @param  zeroGovernor_                     The address of the Zero Governor contract.\n     * @param  cashToken_                        The address of the Cash Token contract.\n     * @param  registrar_                        The address of the Registrar contract.\n     * @param  vault_                            The address of the Vault contract.\n     * @param  zeroToken_                        The address of the Zero Token contract.\n     * @param  proposalFee_                      The proposal fee.\n     * @param  maxTotalZeroRewardPerActiveEpoch_ The maximum amount of zero tokens to reward per active epoch.\n     */\n    constructor(\n        address voteToken_,\n        address emergencyGovernor_,\n        address zeroGovernor_,\n        address cashToken_,\n        address registrar_,\n        address vault_,\n        address zeroToken_,\n        uint256 proposalFee_,\n        uint256 maxTotalZeroRewardPerActiveEpoch_\n    ) BatchGovernor(\"StandardGovernor\", voteToken_) {\n        if ((emergencyGovernor = emergencyGovernor_) == address(0)) revert InvalidEmergencyGovernorAddress();\n        if ((zeroGovernor = zeroGovernor_) == address(0)) revert InvalidZeroGovernorAddress();\n        if ((registrar = registrar_) == address(0)) revert InvalidRegistrarAddress();\n        if ((vault = vault_) == address(0)) revert InvalidVaultAddress();\n        if ((zeroToken = zeroToken_) == address(0)) revert InvalidZeroTokenAddress();\n\n        _setCashToken(cashToken_);\n        _setProposalFee(proposalFee_);\n\n        maxTotalZeroRewardPerActiveEpoch = maxTotalZeroRewardPerActiveEpoch_;\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IGovernor\n    function execute(\n        address[] memory targets_,\n        uint256[] memory values_,\n        bytes[] memory callDatas_,\n        bytes32\n    ) external payable returns (uint256 proposalId_) {\n        _revertIfInvalidProposal(targets_, values_, callDatas_);\n\n        // Proposals have voteStart=N and voteEnd=N, and can be executed only during epoch N+1.\n        uint16 latestPossibleVoteStart_ = _clock() - 1;\n\n        proposalId_ = _tryExecute(callDatas_[0], latestPossibleVoteStart_, latestPossibleVoteStart_);\n\n        ProposalFeeInfo storage proposalFeeInfo_ = _proposalFees[proposalId_];\n        uint256 proposalFee_ = proposalFeeInfo_.fee;\n        address cashToken_ = proposalFeeInfo_.cashToken;\n\n        if (proposalFee_ > 0) {\n            delete _proposalFees[proposalId_];\n            _transfer(cashToken_, _proposals[proposalId_].proposer, proposalFee_);\n        }\n    }\n\n    /// @inheritdoc IGovernor\n    function propose(\n        address[] memory targets_,\n        uint256[] memory values_,\n        bytes[] memory callDatas_,\n        string memory description_\n    ) external override returns (uint256 proposalId_) {\n        uint256 voteStart_;\n\n        (proposalId_, voteStart_) = _propose(targets_, values_, callDatas_, description_);\n\n        // If this is the first proposal for the `voteStart_` epoch, inflate its target total supply of `PowerToken`.\n        if (++numberOfProposalsAt[voteStart_] == 1) {\n            IPowerToken(voteToken).markNextVotingEpochAsActive();\n        }\n\n        uint256 proposalFee_ = proposalFee;\n\n        if (proposalFee_ == 0) return proposalId_;\n\n        address cashToken_ = cashToken;\n\n        _proposalFees[proposalId_] = ProposalFeeInfo({ cashToken: cashToken_, fee: proposalFee_ });\n\n        if (!ERC20Helper.transferFrom(cashToken_, msg.sender, address(this), proposalFee_)) revert TransferFromFailed();\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function setCashToken(address newCashToken_, uint256 newProposalFee_) external onlyZeroGovernor {\n        _setCashToken(newCashToken_);\n\n        IPowerToken(voteToken).setNextCashToken(newCashToken_);\n\n        _setProposalFee(newProposalFee_);\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function sendProposalFeeToVault(uint256 proposalId_) external {\n        ProposalState state_ = state(proposalId_);\n\n        // Must be expired or defeated to have the fee sent to the vault\n        if (state_ != ProposalState.Expired && state_ != ProposalState.Defeated) revert FeeNotDestinedForVault(state_);\n\n        uint256 proposalFee_ = _proposalFees[proposalId_].fee;\n\n        if (proposalFee_ == 0) revert NoFeeToSend();\n\n        address cashToken_ = _proposalFees[proposalId_].cashToken;\n\n        delete _proposalFees[proposalId_];\n\n        emit ProposalFeeSentToVault(proposalId_, cashToken_, proposalFee_);\n\n        // NOTE: Not calling `distribute` on vault since anyone can do it, anytime, and this contract should not need to\n        //       know how the vault works\n        _transfer(cashToken_, vault, proposalFee_);\n    }\n\n    /* ============ Proposal Functions ============ */\n\n    /// @inheritdoc IStandardGovernor\n    function addToList(bytes32 list_, address account_) external onlySelf {\n        _addToList(list_, account_);\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function removeFromList(bytes32 list_, address account_) external onlySelf {\n        _removeFromList(list_, account_);\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function removeFromAndAddToList(bytes32 list_, address accountToRemove_, address accountToAdd_) external onlySelf {\n        _removeFromList(list_, accountToRemove_);\n        _addToList(list_, accountToAdd_);\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function setKey(bytes32 key_, bytes32 value_) external onlySelf {\n        IRegistrar(registrar).setKey(key_, value_);\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function setProposalFee(uint256 newProposalFee_) external onlySelfOrEmergencyGovernor {\n        _setProposalFee(newProposalFee_);\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IGovernor\n    function COUNTING_MODE() external pure returns (string memory) {\n        return \"support=against,for&quorum=for&success=majority\";\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function getProposal(\n        uint256 proposalId_\n    )\n        external\n        view\n        returns (\n            uint48 voteStart_,\n            uint48 voteEnd_,\n            ProposalState state_,\n            uint256 noVotes_,\n            uint256 yesVotes_,\n            address proposer_,\n            uint256 quorum_\n        )\n    {\n        Proposal storage proposal_ = _proposals[proposalId_];\n\n        voteStart_ = proposal_.voteStart;\n        voteEnd_ = _getVoteEnd(proposal_.voteStart);\n        state_ = state(proposalId_);\n        noVotes_ = proposal_.noWeight;\n        yesVotes_ = proposal_.yesWeight;\n        proposer_ = proposal_.proposer;\n        quorum_ = 1;\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function getProposalFee(uint256 proposalId_) external view returns (address cashToken_, uint256 fee_) {\n        ProposalFeeInfo storage proposalFee_ = _proposalFees[proposalId_];\n\n        cashToken_ = proposalFee_.cashToken;\n        fee_ = proposalFee_.fee;\n    }\n\n    /// @inheritdoc IStandardGovernor\n    function hasVotedOnAllProposals(address voter_, uint256 epoch_) external view returns (bool) {\n        return numberOfProposalsVotedOnAt[voter_][epoch_] == numberOfProposalsAt[epoch_];\n    }\n\n    /// @inheritdoc IGovernor\n    function quorum() external pure returns (uint256) {\n        return 1;\n    }\n\n    /// @inheritdoc IGovernor\n    function state(uint256 proposalId_) public view override(BatchGovernor, IGovernor) returns (ProposalState) {\n        Proposal storage proposal_ = _proposals[proposalId_];\n\n        if (proposal_.executed) return ProposalState.Executed;\n\n        uint16 currentEpoch_ = _clock();\n        uint16 voteStart_ = proposal_.voteStart;\n\n        if (voteStart_ == 0) revert ProposalDoesNotExist();\n\n        if (currentEpoch_ < voteStart_) return ProposalState.Pending;\n\n        uint16 voteEnd_ = _getVoteEnd(voteStart_);\n\n        if (currentEpoch_ == voteEnd_) return ProposalState.Active;\n\n        if (proposal_.yesWeight <= proposal_.noWeight) return ProposalState.Defeated;\n\n        unchecked {\n            return (currentEpoch_ <= voteEnd_ + 1) ? ProposalState.Succeeded : ProposalState.Expired;\n        }\n    }\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @dev    Cast votes on several proposals for `voter_`.\n     * @param  voter_       The address of the voter.\n     * @param  proposalIds_ The unique identifiers of the proposals.\n     * @param  supportList_ The type of support to cast for each proposal.\n     * @param  reasonList_  The list of reason per proposal IDs to cast.\n     * @return weight_      The number of votes the voter cast on each proposal.\n     */\n    function _castVotes(\n        address voter_,\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_,\n        string[] memory reasonList_\n    ) internal override returns (uint256 weight_) {\n        uint256 length_ = proposalIds_.length;\n\n        if (length_ == 0) revert EmptyProposalIdsArray();\n\n        if (length_ != supportList_.length) revert ArrayLengthMismatch(length_, supportList_.length);\n\n        if (length_ != reasonList_.length) revert ArrayLengthMismatch(length_, reasonList_.length);\n\n        // In this governor, since the votingPeriod is 0, the snapshot for all active proposals is the previous epoch.\n        weight_ = getVotes(voter_, _clock() - 1);\n\n        for (uint256 index_; index_ < length_; ++index_) {\n            _castVote(voter_, weight_, proposalIds_[index_], supportList_[index_], reasonList_[index_]);\n        }\n    }\n\n    /**\n     * @dev   Adds `account` to `list` at the Registrar.\n     * @param list_    The key for some list.\n     * @param account_ The address of some account to be added.\n     */\n    function _addToList(bytes32 list_, address account_) internal {\n        IRegistrar(registrar).addToList(list_, account_);\n    }\n\n    /**\n     * @dev   Cast `weight_` votes on a proposal with id `proposalId_` for `voter_`.\n     * @param voter_      The address of the voter.\n     * @param weight_     The number of votes the voter is casting.\n     * @param proposalId_ The unique identifier of the proposal.\n     * @param reason_     The reason for which the caller casts their vote, if any.\n     * @param support_    The type of support to cast for the proposal.\n     */\n    function _castVote(\n        address voter_,\n        uint256 weight_,\n        uint256 proposalId_,\n        uint8 support_,\n        string memory reason_\n    ) internal override {\n        ProposalState state_ = state(proposalId_);\n\n        if (state_ != ProposalState.Active) revert ProposalInactive(state_);\n\n        super._castVote(voter_, weight_, proposalId_, support_, reason_);\n\n        uint16 currentEpoch_ = _clock();\n\n        // NOTE: Will only get beyond this statement once per epoch as there is no way to vote on more proposals than\n        //       exist in this epoch.\n        if (++numberOfProposalsVotedOnAt[voter_][currentEpoch_] != numberOfProposalsAt[currentEpoch_]) return;\n\n        emit HasVotedOnAllProposals(voter_, currentEpoch_);\n\n        IPowerToken(voteToken).markParticipation(voter_);\n\n        uint256 reward_ = (maxTotalZeroRewardPerActiveEpoch * weight_) / _getTotalSupply(currentEpoch_ - 1);\n\n        if (reward_ == 0) return;\n\n        IZeroToken(zeroToken).mint(voter_, reward_);\n    }\n\n    /**\n     * @dev   Creates a new proposal with the given parameters.\n     * @param proposalId_ The unique identifier of the proposal.\n     * @param voteStart_  The epoch at which the proposal will start collecting votes.\n     */\n    function _createProposal(uint256 proposalId_, uint16 voteStart_) internal override {\n        _proposals[proposalId_] = Proposal({\n            voteStart: voteStart_,\n            executed: false,\n            proposer: msg.sender,\n            thresholdRatio: 0,\n            noWeight: 0,\n            yesWeight: 0\n        });\n    }\n\n    /**\n     * @dev   Removes `account_` from `list_` at the Registrar.\n     * @param list_    The key for some list.\n     * @param account_ The address of some account to be removed.\n     */\n    function _removeFromList(bytes32 list_, address account_) internal {\n        IRegistrar(registrar).removeFromList(list_, account_);\n    }\n\n    /**\n     * @dev   Set cash token to `newCashToken_`.\n     * @param newCashToken_ The address of the new cash token.\n     */\n    function _setCashToken(address newCashToken_) internal {\n        if (newCashToken_ == address(0)) revert InvalidCashTokenAddress();\n\n        emit CashTokenSet(cashToken = newCashToken_);\n    }\n\n    /**\n     * @dev   Set proposal fee to `newProposalFee_`.\n     * @param newProposalFee_ The new proposal fee.\n     */\n    function _setProposalFee(uint256 newProposalFee_) internal {\n        emit ProposalFeeSet(proposalFee = newProposalFee_);\n    }\n\n    /**\n     * @dev   Transfer `amount_` of `token_` to `to_`.\n     * @param token_  The address of the token to transfer.\n     * @param to_     The address of the recipient.\n     * @param amount_ The amount of tokens to transfer.\n     */\n    function _transfer(address token_, address to_, uint256 amount_) internal {\n        if (!ERC20Helper.transfer(token_, to_, amount_)) revert TransferFailed();\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Returns the number of clock values that must elapse before voting begins for a newly created proposal.\n     * @return The voting delay.\n     */\n    function _votingDelay() internal view override returns (uint16) {\n        return clock() % 2 == 1 ? 2 : 1; // Voting epochs are odd numbered\n    }\n\n    /**\n     * @dev   All proposals target this contract itself, and must call one of the listed functions to be valid.\n     * @param callData_ The call data to check.\n     */\n    function _revertIfInvalidCalldata(bytes memory callData_) internal pure override {\n        bytes4 func_ = bytes4(callData_);\n        uint256 length = callData_.length;\n\n        if (\n            !(func_ == this.addToList.selector && length == _SELECTOR_PLUS_2_ARGS) &&\n            !(func_ == this.removeFromList.selector && length == _SELECTOR_PLUS_2_ARGS) &&\n            !(func_ == this.removeFromAndAddToList.selector && length == _SELECTOR_PLUS_3_ARGS) &&\n            !(func_ == this.setKey.selector && length == _SELECTOR_PLUS_2_ARGS) &&\n            !(func_ == this.setProposalFee.selector && length == _SELECTOR_PLUS_1_ARGS)\n        ) revert InvalidCallData();\n    }\n\n    /**\n     * @dev    Returns the number of clock values between the vote start and vote end.\n     * @return The voting period.\n     */\n    function _votingPeriod() internal pure override returns (uint16) {\n        return 0;\n    }\n}\n"
      },
      "lib/ttg/lib/erc20-helper/src/ERC20Helper.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.7;\n\nimport { IERC20Like } from \"./interfaces/IERC20Like.sol\";\n\n/**\n * @title Small Library to standardize erc20 token interactions.\n */\nlibrary ERC20Helper {\n\n    /**************************************************************************************************************************************/\n    /*** Internal Functions                                                                                                             ***/\n    /**************************************************************************************************************************************/\n\n    function transfer(address token_, address to_, uint256 amount_) internal returns (bool success_) {\n        return _call(token_, abi.encodeWithSelector(IERC20Like.transfer.selector, to_, amount_));\n    }\n\n    function transferFrom(address token_, address from_, address to_, uint256 amount_) internal returns (bool success_) {\n        return _call(token_, abi.encodeWithSelector(IERC20Like.transferFrom.selector, from_, to_, amount_));\n    }\n\n    function approve(address token_, address spender_, uint256 amount_) internal returns (bool success_) {\n        // If setting approval to zero fails, return false.\n        if (!_call(token_, abi.encodeWithSelector(IERC20Like.approve.selector, spender_, uint256(0)))) return false;\n\n        // If `amount_` is zero, return true as the previous step already did this.\n        if (amount_ == uint256(0)) return true;\n\n        // Return the result of setting the approval to `amount_`.\n        return _call(token_, abi.encodeWithSelector(IERC20Like.approve.selector, spender_, amount_));\n    }\n\n    function _call(address token_, bytes memory data_) private returns (bool success_) {\n        if (token_.code.length == uint256(0)) return false;\n\n        bytes memory returnData;\n        ( success_, returnData ) = token_.call(data_);\n\n        return success_ && (returnData.length == uint256(0) || abi.decode(returnData, (bool)));\n    }\n\n}\n"
      },
      "lib/ttg/src/abstract/interfaces/IGovernor.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC712 } from \"../../../lib/common/src/interfaces/IERC712.sol\";\n\nimport { IERC6372 } from \"./IERC6372.sol\";\n\n/**\n * @title  Minimal OpenZeppelin-style, Tally-compatible governor.\n * @author M^0 Labs\n */\ninterface IGovernor is IERC6372, IERC712 {\n    /* ============ Enums ============ */\n\n    /**\n     * @notice Proposal state.\n     * @param  Pending   The proposal has been created, but the vote has not started yet.\n     * @param  Active    The proposal is currently in the voting period.\n     * @param  Canceled  The proposal has been canceled.\n     * @param  Defeated  The proposal has been defeated.\n     * @param  Succeeded The proposal has succeeded.\n     * @param  Queued    The proposal has been queued.\n     * @param  Expired   The proposal has expired.\n     * @param  Executed  The proposal has been executed.\n     */\n    enum ProposalState {\n        Pending,\n        Active,\n        Canceled, // never used by TTG.\n        Defeated,\n        Succeeded,\n        Queued, // never used by TTG.\n        Expired,\n        Executed\n    }\n\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when a proposal has been created.\n     * @param  proposalId  The unique identifier for the proposal.\n     * @param  proposer    The address of the account that created the proposal.\n     * @param  targets     An array of addresses that will be called upon the execution.\n     * @param  values      An array of ETH amounts that will be sent to each respective target upon execution.\n     * @param  signatures  Empty string array required to be compatible with OZ governor contract.\n     * @param  callDatas   An array of call data used to call each respective target upon execution.\n     * @param  voteStart   The first clock value when voting on the proposal is allowed.\n     * @param  voteEnd     The last clock value when voting on the proposal is allowed.\n     * @param  description The string of the description of the proposal.\n     */\n    event ProposalCreated(\n        uint256 proposalId,\n        address proposer,\n        address[] targets,\n        uint256[] values,\n        string[] signatures,\n        bytes[] callDatas,\n        uint256 voteStart,\n        uint256 voteEnd,\n        string description\n    );\n\n    /**\n     * @notice Emitted when a proposal has been executed.\n     * @param  proposalId The unique identifier for the proposal.\n     */\n    event ProposalExecuted(uint256 proposalId);\n\n    /**\n     * @notice Emitted when a vote for a proposal with id `proposalId` has been cast by `voter`.\n     * @param  voter      The address of the account that has casted their vote.\n     * @param  proposalId The unique identifier for the proposal.\n     * @param  support    The type of support that has been cast for the proposal.\n     * @param  weight     The number of votes cast.\n     * @param  reason     The string of the reason `voter` has cast their vote, if any.\n     */\n    event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Allows the caller to cast a vote on a proposal with id `proposalId`.\n     * @param  proposalId The unique identifier for the proposal.\n     * @param  support    The type of support to cast for the proposal.\n     * @return weight     The number of votes cast.\n     */\n    function castVote(uint256 proposalId, uint8 support) external returns (uint256 weight);\n\n    /**\n     * @notice Allows a signer to cast a vote on a proposal with id `proposalId` via an ECDSA secp256k1 signature.\n     * @param  proposalId The unique identifier for the proposal.\n     * @param  support    The type of support to cast for the proposal.\n     * @param  v          An ECDSA secp256k1 signature parameter.\n     * @param  r          An ECDSA secp256k1 signature parameter.\n     * @param  s          An ECDSA secp256k1 signature parameter.\n     * @return weight     The number of votes cast.\n     */\n    function castVoteBySig(\n        uint256 proposalId,\n        uint8 support,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows `voter` to cast a vote on a proposal with id `proposalId` via an arbitrary signature.\n     * @param  voter      The address of the account that casting their vote, and purported to have signed.\n     * @param  proposalId The unique identifier for the proposal.\n     * @param  support    The type of support to cast for the proposal.\n     * @param  signature  An arbitrary signature.\n     * @return weight     The number of votes cast.\n     */\n    function castVoteBySig(\n        address voter,\n        uint256 proposalId,\n        uint8 support,\n        bytes memory signature\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows the caller to cast a vote with reason on a proposal with id `proposalId`.\n     * @param  proposalId The unique identifier for the proposal.\n     * @param  support    The type of support to cast for the proposal.\n     * @param  reason     The reason for which the caller casts their vote, if any.\n     * @return weight     The number of votes cast.\n     */\n    function castVoteWithReason(\n        uint256 proposalId,\n        uint8 support,\n        string calldata reason\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows a signer to cast a vote with reason on a proposal with id `proposalId`\n     *         via an ECDSA secp256k1 signature.\n     * @param  proposalId The unique identifier for the proposal.\n     * @param  support    The type of support to cast for the proposal.\n     * @param  reason     The reason for which the caller casts their vote, if any.\n     * @param  v          An ECDSA secp256k1 signature parameter.\n     * @param  r          An ECDSA secp256k1 signature parameter.\n     * @param  s          An ECDSA secp256k1 signature parameter.\n     * @return weight     The number of votes cast.\n     */\n    function castVoteWithReasonBySig(\n        uint256 proposalId,\n        uint8 support,\n        string calldata reason,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows `voter` to cast a vote with reason on a proposal with id `proposalId` via an arbitrary signature.\n     * @param  voter      The address of the account that casting their vote, and purported to have signed.\n     * @param  proposalId The unique identifier for the proposal.\n     * @param  support    The type of support to cast for the proposal.\n     * @param  reason     The reason for which the caller casts their vote, if any.\n     * @param  signature  An arbitrary signature.\n     * @return weight     The number of votes cast.\n     */\n    function castVoteWithReasonBySig(\n        address voter,\n        uint256 proposalId,\n        uint8 support,\n        string calldata reason,\n        bytes memory signature\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows the caller to execute a proposal.\n     * @param  targets         An array of addresses that will be called upon the execution.\n     * @param  values          An array of ETH amounts that will be sent to each respective target upon execution.\n     * @param  callDatas       An array of call data used to call each respective target upon execution.\n     * @param  descriptionHash The hash of the string of the description of the proposal.\n     * @return proposalId      The unique identifier for the proposal.\n     */\n    function execute(\n        address[] memory targets,\n        uint256[] memory values,\n        bytes[] memory callDatas,\n        bytes32 descriptionHash\n    ) external payable returns (uint256 proposalId);\n\n    /**\n     * @notice Allows the caller to create a proposal.\n     * @param  targets     An array of addresses that will be called upon the execution.\n     * @param  values      An array of ETH amounts that will be sent to each respective target upon execution.\n     * @param  callDatas   An array of call data used to call each respective target upon execution.\n     * @param  description The string of the description of the proposal.\n     * @return proposalId  The unique identifier for the proposal.\n     */\n    function propose(\n        address[] memory targets,\n        uint256[] memory values,\n        bytes[] memory callDatas,\n        string memory description\n    ) external returns (uint256 proposalId);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice module:voting\n     * @dev    A description of the possible \"support\" values for castVote and the way these votes are counted, meant to\n     *         be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded\n     *         sequence of key-value pairs that each describe one aspect, for example `support=for,against&quorum=for`.\n     *         The string can be decoded by the standard URLSearchParams JavaScript class.\n     */\n    function COUNTING_MODE() external view returns (string memory);\n\n    /**\n     * @notice Returns the voting power of `account` at clock value `timepoint`.\n     * @param  account   The address of the account with voting power.\n     * @param  timepoint The point in time, according to the clock mode the contract is operating on.\n     * @return The voting power of `account` at `timepoint`.\n     */\n    function getVotes(address account, uint256 timepoint) external view returns (uint256);\n\n    /**\n     * @notice Returns the unique identifier for the proposal if it were created at this exact moment.\n     * @param  targets         An array of addresses that will be called upon the execution.\n     * @param  values          An array of ETH amounts that will be sent to each respective target upon execution.\n     * @param  callDatas       An array of call data used to call each respective target upon execution.\n     * @param  descriptionHash The hash of the string of the description of the proposal.\n     * @return The unique identifier for the proposal.\n     */\n    function hashProposal(\n        address[] memory targets,\n        uint256[] memory values,\n        bytes[] memory callDatas,\n        bytes32 descriptionHash\n    ) external view returns (uint256);\n\n    /**\n     * @notice Returns whether `account` has voted on the proposal with identifier `proposalId`.\n     * @param  proposalId The unique identifier for the proposal.\n     * @param  account    The address of some account.\n     * @return Whether `account` has already voted on the proposal.\n     */\n    function hasVoted(uint256 proposalId, address account) external view returns (bool);\n\n    /// @notice Returns the name of the contract.\n    function name() external view returns (string memory);\n\n    /**\n     * @notice Returns the last clock value when voting on the proposal with identifier `proposalId` is allowed.\n     * @param  proposalId The unique identifier for the proposal.\n     * @return The last clock value when voting on the proposal is allowed.\n     */\n    function proposalDeadline(uint256 proposalId) external view returns (uint256);\n\n    /**\n     * @notice Returns the account that created the proposal with identifier `proposalId`.\n     * @param  proposalId The unique identifier for the proposal.\n     * @return The address of the account that created the proposal.\n     */\n    function proposalProposer(uint256 proposalId) external view returns (address);\n\n    /**\n     * @notice Returns the clock value used to retrieve voting power to vote on proposal with identifier `proposalId`.\n     * @param  proposalId The unique identifier for the proposal.\n     * @return The clock value used to retrieve voting power.\n     */\n    function proposalSnapshot(uint256 proposalId) external view returns (uint256);\n\n    /// @notice Returns the required voting power an account needs to create a proposal.\n    function proposalThreshold() external view returns (uint256);\n\n    /**\n     * @notice Returns the vote support totals for the proposal with identifier `proposalId`.\n     * @param  proposalId   The unique identifier for the proposal.\n     * @return noVotes      The amount of votes cast against the proposal.\n     * @return yesVotes     The amount of votes cast for the proposal.\n     * @return abstainVotes The amount of votes cast in abstention the proposal.\n     */\n    function proposalVotes(\n        uint256 proposalId\n    ) external view returns (uint256 noVotes, uint256 yesVotes, uint256 abstainVotes);\n\n    /// @notice Returns the minimum number of eligible (COUNTING_MODE) votes for a proposal to succeed.\n    function quorum() external view returns (uint256);\n\n    /**\n     * @notice Returns the state of a proposal with identifier `proposalId`.\n     * @param  proposalId The unique identifier for the proposal.\n     * @return The state of the proposal.\n     */\n    function state(uint256 proposalId) external view returns (ProposalState);\n\n    /// @notice Returns the EIP-5805 token contact used for determine voting power and total supplies.\n    function token() external view returns (address);\n\n    /// @notice Returns the number of clock values that must elapse before voting begins for a newly created proposal.\n    function votingDelay() external view returns (uint256);\n\n    /// @notice Returns the number of clock values between the vote start and vote end.\n    function votingPeriod() external view returns (uint256);\n\n    /// @notice Returns the EIP712 typehash used in the encoding of the digest for `castVoteBySig` function.\n    function BALLOT_TYPEHASH() external pure returns (bytes32);\n\n    /// @notice Returns the EIP712 typehash used in the encoding of the digest for `castVoteWithReasonBySig` function.\n    function BALLOT_WITH_REASON_TYPEHASH() external pure returns (bytes32);\n}\n"
      },
      "lib/ttg/src/abstract/BatchGovernor.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { ERC712Extended } from \"../../lib/common/src/ERC712Extended.sol\";\n\nimport { PureEpochs } from \"../libs/PureEpochs.sol\";\n\nimport { IBatchGovernor } from \"./interfaces/IBatchGovernor.sol\";\nimport { IEpochBasedVoteToken } from \"./interfaces/IEpochBasedVoteToken.sol\";\nimport { IERC6372 } from \"./interfaces/IERC6372.sol\";\nimport { IGovernor } from \"./interfaces/IGovernor.sol\";\n\n/**\n * @title  Extension for Governor with specialized strict proposal parameters, vote batching, and an epoch clock.\n * @author M^0 Labs\n */\nabstract contract BatchGovernor is IBatchGovernor, ERC712Extended {\n    /* ============ Structs ============ */\n\n    /**\n     * @notice Proposal struct for storing all relevant proposal information.\n     * @param  voteStart      The epoch at which voting begins, inclusively.\n     * @param  executed       Whether or not the proposal has been executed.\n     * @param  proposer       The address of the proposer.\n     * @param  thresholdRatio The ratio of yes votes required for a proposal to meet quorum and succeed.\n     * @param  noWeight       The total number of votes against the proposal.\n     * @param  yesWeight      The total number of votes for the proposal.\n     */\n    struct Proposal {\n        // 1st slot\n        uint16 voteStart;\n        bool executed;\n        address proposer;\n        uint16 thresholdRatio;\n        // 2nd slot\n        uint256 noWeight;\n        // 3rd slot\n        uint256 yesWeight;\n    }\n\n    /* ============ Variables ============ */\n\n    /// @dev Length constant for calldata with no argument.\n    uint256 internal constant _SELECTOR_PLUS_0_ARGS = 4;\n\n    /// @dev Length constant for calldata with one argument.\n    uint256 internal constant _SELECTOR_PLUS_1_ARGS = 36;\n\n    /// @dev Length constant for calldata with two arguments.\n    uint256 internal constant _SELECTOR_PLUS_2_ARGS = 68;\n\n    /// @dev Length constant for calldata with three arguments.\n    uint256 internal constant _SELECTOR_PLUS_3_ARGS = 100;\n\n    // keccak256(\"Ballot(uint256 proposalId,uint8 support)\")\n    /// @inheritdoc IGovernor\n    bytes32 public constant BALLOT_TYPEHASH = 0x150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f;\n\n    // keccak256(\"BallotWithReason(uint256 proposalId,uint8 support,string reason)\")\n    /// @inheritdoc IGovernor\n    bytes32 public constant BALLOT_WITH_REASON_TYPEHASH =\n        0x7949bd92105c02f48ca245aa185f4a7a4d7185641d59b186ac64abeb44964f0c;\n\n    // keccak256(\"Ballots(uint256[] proposalIds,uint8[] supportList)\")\n    /// @inheritdoc IBatchGovernor\n    bytes32 public constant BALLOTS_TYPEHASH = 0x9a121fc10d6025acfc09275f9709796b68831733b5bbac0d510d13f85b1b730f;\n\n    // keccak256(\"BallotsWithReason(uint256[] proposalIds,uint8[] supportList,string[] reasonList)\")\n    /// @inheritdoc IBatchGovernor\n    bytes32 public constant BALLOTS_WITH_REASON_TYPEHASH =\n        0xa891f76027ef63a24501b9dd3b0c779b49ad26d2328e9d423640209d1ad4fcc4;\n\n    /// @inheritdoc IBatchGovernor\n    address public immutable voteToken;\n\n    /// @dev The list of proposals per proposal ID.\n    mapping(uint256 proposalId => Proposal proposal) internal _proposals;\n\n    /// @inheritdoc IGovernor\n    mapping(uint256 proposalId => mapping(address voter => bool hasVoted)) public hasVoted;\n\n    /* ============ Modifiers ============ */\n\n    /// @dev Reverts if the caller is not the contract itself.\n    modifier onlySelf() {\n        _revertIfNotSelf();\n        _;\n    }\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Construct a new BatchGovernor contract.\n     * @param  name_      The name of the contract. Used to compute EIP712 domain separator.\n     * @param  voteToken_ The address of the token used to vote.\n     */\n    constructor(string memory name_, address voteToken_) ERC712Extended(name_) {\n        if ((voteToken = voteToken_) == address(0)) revert InvalidVoteTokenAddress();\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IGovernor\n    function castVote(uint256 proposalId_, uint8 support_) external returns (uint256 weight_) {\n        return _castVote(msg.sender, proposalId_, support_, \"\");\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function castVotes(\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_\n    ) external returns (uint256 weight_) {\n        return _castVotes(msg.sender, proposalIds_, supportList_, new string[](proposalIds_.length));\n    }\n\n    /// @inheritdoc IGovernor\n    function castVoteWithReason(\n        uint256 proposalId_,\n        uint8 support_,\n        string calldata reason_\n    ) external returns (uint256 weight_) {\n        return _castVote(msg.sender, proposalId_, support_, reason_);\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function castVotesWithReason(\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_,\n        string[] calldata reasonList_\n    ) external returns (uint256 weight_) {\n        return _castVotes(msg.sender, proposalIds_, supportList_, reasonList_);\n    }\n\n    /// @inheritdoc IGovernor\n    function castVoteBySig(\n        uint256 proposalId_,\n        uint8 support_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) external returns (uint256 weight_) {\n        return\n            _castVote(\n                _getSignerAndRevertIfInvalidSignature(_getBallotDigest(proposalId_, support_), v_, r_, s_),\n                proposalId_,\n                support_,\n                \"\"\n            );\n    }\n\n    /// @inheritdoc IGovernor\n    function castVoteBySig(\n        address voter_,\n        uint256 proposalId_,\n        uint8 support_,\n        bytes memory signature_\n    ) external returns (uint256 weight_) {\n        _revertIfInvalidSignature(voter_, _getBallotDigest(proposalId_, support_), signature_);\n\n        return _castVote(voter_, proposalId_, support_, \"\");\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function castVotesBySig(\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) external returns (uint256 weight_) {\n        return\n            _castVotes(\n                _getSignerAndRevertIfInvalidSignature(\n                    _getBallotsDigest(\n                        keccak256(abi.encodePacked(proposalIds_)),\n                        keccak256(abi.encodePacked(supportList_))\n                    ),\n                    v_,\n                    r_,\n                    s_\n                ),\n                proposalIds_,\n                supportList_,\n                new string[](proposalIds_.length)\n            );\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function castVotesBySig(\n        address voter_,\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_,\n        bytes memory signature_\n    ) external returns (uint256 weight_) {\n        _revertIfInvalidSignature(\n            voter_,\n            _getBallotsDigest(keccak256(abi.encodePacked(proposalIds_)), keccak256(abi.encodePacked(supportList_))),\n            signature_\n        );\n\n        return _castVotes(voter_, proposalIds_, supportList_, new string[](proposalIds_.length));\n    }\n\n    /// @inheritdoc IGovernor\n    function castVoteWithReasonBySig(\n        uint256 proposalId_,\n        uint8 support_,\n        string calldata reason_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) external returns (uint256 weight_) {\n        return\n            _castVote(\n                _getSignerAndRevertIfInvalidSignature(\n                    _getBallotWithReasonDigest(proposalId_, support_, reason_),\n                    v_,\n                    r_,\n                    s_\n                ),\n                proposalId_,\n                support_,\n                reason_\n            );\n    }\n\n    /// @inheritdoc IGovernor\n    function castVoteWithReasonBySig(\n        address voter_,\n        uint256 proposalId_,\n        uint8 support_,\n        string calldata reason_,\n        bytes memory signature_\n    ) external returns (uint256 weight_) {\n        _revertIfInvalidSignature(voter_, _getBallotWithReasonDigest(proposalId_, support_, reason_), signature_);\n\n        return _castVote(voter_, proposalId_, support_, reason_);\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function castVotesWithReasonBySig(\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_,\n        string[] calldata reasonList_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) external returns (uint256 weight_) {\n        return\n            _castVotes(\n                _getSignerAndRevertIfInvalidSignature(\n                    _getBallotsWithReasonDigest(\n                        keccak256(abi.encodePacked(proposalIds_)),\n                        keccak256(abi.encodePacked(supportList_)),\n                        _getReasonListHash(reasonList_)\n                    ),\n                    v_,\n                    r_,\n                    s_\n                ),\n                proposalIds_,\n                supportList_,\n                reasonList_\n            );\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function castVotesWithReasonBySig(\n        address voter_,\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_,\n        string[] calldata reasonList_,\n        bytes memory signature_\n    ) external returns (uint256 weight_) {\n        _revertIfInvalidSignature(\n            voter_,\n            _getBallotsWithReasonDigest(\n                keccak256(abi.encodePacked(proposalIds_)),\n                keccak256(abi.encodePacked(supportList_)),\n                _getReasonListHash(reasonList_)\n            ),\n            signature_\n        );\n\n        return _castVotes(voter_, proposalIds_, supportList_, reasonList_);\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IGovernor\n    function hashProposal(\n        address[] memory,\n        uint256[] memory,\n        bytes[] memory callDatas_,\n        bytes32\n    ) external view returns (uint256) {\n        return _hashProposal(callDatas_[0]);\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function hashProposal(bytes memory callData_) external view returns (uint256) {\n        return _hashProposal(callData_);\n    }\n\n    /// @inheritdoc IGovernor\n    function name() external view returns (string memory) {\n        return _name;\n    }\n\n    /// @inheritdoc IGovernor\n    function proposalDeadline(uint256 proposalId_) external view returns (uint256) {\n        return _getVoteEnd(_proposals[proposalId_].voteStart);\n    }\n\n    /// @inheritdoc IGovernor\n    function proposalProposer(uint256 proposalId_) external view returns (address) {\n        return _proposals[proposalId_].proposer;\n    }\n\n    /// @inheritdoc IGovernor\n    function proposalSnapshot(uint256 proposalId_) external view returns (uint256) {\n        return _proposals[proposalId_].voteStart - 1;\n    }\n\n    /// @inheritdoc IGovernor\n    function proposalVotes(uint256 proposalId_) external view returns (uint256, uint256, uint256) {\n        Proposal storage proposal_ = _proposals[proposalId_];\n\n        return (proposal_.noWeight, proposal_.yesWeight, 0);\n    }\n\n    /// @inheritdoc IGovernor\n    function token() external view returns (address) {\n        return voteToken;\n    }\n\n    /// @inheritdoc IERC6372\n    function CLOCK_MODE() external pure returns (string memory) {\n        return PureEpochs.clockMode();\n    }\n\n    /// @inheritdoc IGovernor\n    function proposalThreshold() external pure returns (uint256) {\n        return 0;\n    }\n\n    /// @inheritdoc IERC6372\n    function clock() public view returns (uint48) {\n        return _clock();\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function getBallotDigest(uint256 proposalId_, uint8 support_) external view returns (bytes32) {\n        return _getBallotDigest(proposalId_, support_);\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function getBallotsDigest(\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_\n    ) external view returns (bytes32) {\n        return _getBallotsDigest(keccak256(abi.encodePacked(proposalIds_)), keccak256(abi.encodePacked(supportList_)));\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function getBallotWithReasonDigest(\n        uint256 proposalId_,\n        uint8 support_,\n        string calldata reason_\n    ) external view returns (bytes32) {\n        return _getBallotWithReasonDigest(proposalId_, support_, reason_);\n    }\n\n    /// @inheritdoc IBatchGovernor\n    function getBallotsWithReasonDigest(\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_,\n        string[] calldata reasonList_\n    ) external view returns (bytes32) {\n        return\n            _getBallotsWithReasonDigest(\n                keccak256(abi.encodePacked(proposalIds_)),\n                keccak256(abi.encodePacked(supportList_)),\n                _getReasonListHash(reasonList_)\n            );\n    }\n\n    /// @inheritdoc IGovernor\n    function getVotes(address account_, uint256 timepoint_) public view returns (uint256) {\n        return IEpochBasedVoteToken(voteToken).getPastVotes(account_, timepoint_);\n    }\n\n    /// @inheritdoc IGovernor\n    function state(uint256 proposalId_) public view virtual returns (ProposalState);\n\n    /// @inheritdoc IGovernor\n    function votingDelay() public view returns (uint256) {\n        return _votingDelay();\n    }\n\n    /// @inheritdoc IGovernor\n    function votingPeriod() public view returns (uint256) {\n        return _votingPeriod();\n    }\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @dev    Cast votes on several proposals for `voter_`.\n     * @param  voter_       The address of the voter.\n     * @param  proposalIds_ The list of unique proposal IDs being voted on.\n     * @param  supportList_ The list of support type per proposal IDs to cast.\n     * @param  reasonList_  The list of reason per proposal IDs to cast.\n     * @return weight_      The number of votes the voter cast on each proposal.\n     */\n    function _castVotes(\n        address voter_,\n        uint256[] calldata proposalIds_,\n        uint8[] calldata supportList_,\n        string[] memory reasonList_\n    ) internal virtual returns (uint256 weight_) {\n        uint256 length_ = proposalIds_.length;\n\n        if (length_ == 0) revert EmptyProposalIdsArray();\n\n        if (length_ != supportList_.length) revert ArrayLengthMismatch(length_, supportList_.length);\n\n        if (length_ != reasonList_.length) revert ArrayLengthMismatch(length_, reasonList_.length);\n\n        for (uint256 index_; index_ < length_; ++index_) {\n            weight_ = _castVote(voter_, proposalIds_[index_], supportList_[index_], reasonList_[index_]);\n        }\n    }\n\n    /**\n     * @dev    Cast votes on proposal for `voter_`.\n     * @param  voter_      The address of the voter.\n     * @param  proposalId_ The unique identifier of the proposal.\n     * @param  support_    The type of support to cast for the proposal.\n     * @param  reason_     The reason for which the caller casts their vote, if any.\n     * @return weight_     The number of votes cast.\n     */\n    function _castVote(\n        address voter_,\n        uint256 proposalId_,\n        uint8 support_,\n        string memory reason_\n    ) internal returns (uint256 weight_) {\n        ProposalState state_ = state(proposalId_);\n\n        if (state_ != ProposalState.Active) revert ProposalInactive(state_);\n\n        unchecked {\n            // NOTE: Can be done unchecked since `voteStart` is always greater than 0.\n            weight_ = getVotes(voter_, _proposals[proposalId_].voteStart - 1);\n        }\n\n        _castVote(voter_, weight_, proposalId_, support_, reason_);\n    }\n\n    /**\n     * @dev   Cast `weight_` votes on a proposal with id `proposalId_` for `voter_`.\n     * @param voter_      The address of the voter.\n     * @param weight_     The number of votes the voter is casting.\n     * @param proposalId_ The unique identifier of the proposal.\n     * @param support_    The type of support to cast for the proposal.\n     * @param reason_     The reason for which the caller casts their vote, if any.\n     */\n    function _castVote(\n        address voter_,\n        uint256 weight_,\n        uint256 proposalId_,\n        uint8 support_,\n        string memory reason_\n    ) internal virtual {\n        if (weight_ == 0) revert ZeroVotingPower();\n        if (hasVoted[proposalId_][voter_]) revert AlreadyVoted();\n\n        hasVoted[proposalId_][voter_] = true;\n\n        unchecked {\n            // NOTE: Can be done unchecked since total supply is less than `type(uint256).max`.\n            if (VoteType(support_) == VoteType.No) {\n                _proposals[proposalId_].noWeight += weight_;\n            } else {\n                _proposals[proposalId_].yesWeight += weight_;\n            }\n        }\n\n        emit VoteCast(voter_, proposalId_, support_, weight_, reason_);\n    }\n\n    /**\n     * @dev   Creates a new proposal with the given parameters.\n     * @param proposalId_ The unique identifier of the proposal.\n     * @param voteStart_  The epoch at which the proposal will start collecting votes.\n     */\n    function _createProposal(uint256 proposalId_, uint16 voteStart_) internal virtual;\n\n    /**\n     * @dev    Executes a proposal given its call data and voteStart (which are unique to it).\n     * @param  callData_   The call data to execute.\n     * @param  voteStart_  The epoch at which the proposal started collecting votes.\n     * @return proposalId_ The unique identifier of the proposal that matched the criteria.\n     */\n    function _execute(bytes memory callData_, uint16 voteStart_) internal virtual returns (uint256 proposalId_) {\n        proposalId_ = _hashProposal(callData_, voteStart_);\n\n        Proposal storage proposal_ = _proposals[proposalId_];\n\n        if (proposal_.voteStart != voteStart_) return 0;\n\n        if (state(proposalId_) != ProposalState.Succeeded) return 0;\n\n        proposal_.executed = true;\n\n        emit ProposalExecuted(proposalId_);\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success_, bytes memory data_) = address(this).call(callData_);\n\n        if (!success_) revert ExecutionFailed(data_);\n    }\n\n    /**\n     * @dev    Internal handler for making proposals.\n     * @param  targets_     An array of addresses that will be called upon the execution.\n     * @param  values_      An array of ETH amounts that will be sent to each respective target upon execution.\n     * @param  callDatas_   An array of call data used to call each respective target upon execution.\n     * @param  description_ The string of the description of the proposal.\n     * @return proposalId_  The unique identifier of the proposal.\n     * @return voteStart_   The timepoint at which voting on the proposal begins, inclusively.\n     */\n    function _propose(\n        address[] memory targets_,\n        uint256[] memory values_,\n        bytes[] memory callDatas_,\n        string memory description_\n    ) internal returns (uint256 proposalId_, uint16 voteStart_) {\n        _revertIfInvalidProposal(targets_, values_, callDatas_);\n\n        voteStart_ = _voteStart();\n\n        proposalId_ = _hashProposal(callDatas_[0], voteStart_);\n\n        if (_proposals[proposalId_].voteStart != 0) revert ProposalExists();\n\n        _createProposal(proposalId_, voteStart_);\n\n        emit ProposalCreated(\n            proposalId_,\n            msg.sender,\n            targets_,\n            values_,\n            new string[](targets_.length),\n            callDatas_,\n            voteStart_,\n            _getVoteEnd(voteStart_),\n            description_\n        );\n    }\n\n    /**\n     * @dev    This function tries to execute a proposal based on the call data and a range of possible vote starts.\n     *         This is needed due to the fact that proposalId's are generated based on the call data and vote start\n     *         time, and so an executed function will need this in order to attempt to find and execute a proposal given\n     *         a known range of possible vote start times which depends on how the inheriting implementation\n     *         determines the vote start time and expiry of proposals based on the time of the proposal creation.\n     * @param  callData_          An array of call data used to call each respective target upon execution.\n     * @param  latestVoteStart_   The most recent vote start to use in attempting to search for the proposal.\n     * @param  earliestVoteStart_ The least recent vote start to use in attempting to search for the proposal.\n     * @return proposalId_        The unique identifier of the most recent proposal that matched the criteria.\n     */\n    function _tryExecute(\n        bytes memory callData_,\n        uint16 latestVoteStart_,\n        uint16 earliestVoteStart_\n    ) internal returns (uint256 proposalId_) {\n        if (msg.value != 0) revert InvalidValue();\n\n        // Non-existent proposals have a default vote start of 0\n        if (earliestVoteStart_ == 0) revert InvalidVoteStart();\n\n        while (latestVoteStart_ >= earliestVoteStart_) {\n            // `proposalId_` will be 0 if no proposal exists for `callData_` and `latestVoteStart_`, or if the proposal\n            // is not in  a `Succeeded` state. It will be executed otherwise. (see `_execute`)\n            unchecked {\n                proposalId_ = _execute(callData_, latestVoteStart_--);\n            }\n\n            // If the `proposalId_` is not 0, then a proposal matching `callData_` and `latestVoteStart_` was found, in\n            // a Succeeded state, and was executed, so return it.\n            if (proposalId_ != 0) return proposalId_;\n        }\n\n        revert ProposalCannotBeExecuted(); // No proposal matching the criteria was found/executed.\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /// @dev Returns the current timepoint according to the mode the contract is operating on.\n    function _clock() internal view returns (uint16) {\n        return PureEpochs.currentEpoch();\n    }\n\n    /**\n     * @dev    Returns the vote token's total supply at `timepoint_`.\n     * @param  timepoint_ The clock value at which to query the vote token's total supply.\n     * @return The vote token's total supply at the `timepoint` clock value.\n     */\n    function _getTotalSupply(uint16 timepoint_) internal view returns (uint256) {\n        return IEpochBasedVoteToken(voteToken).pastTotalSupply(timepoint_);\n    }\n\n    /// @dev Returns the timepoint at which voting would start for a proposal created in current timepoint.\n    function _voteStart() internal view returns (uint16) {\n        unchecked {\n            return _clock() + _votingDelay();\n        }\n    }\n\n    /**\n     * @dev    Returns the timepoint at which voting would end given a timepoint at which voting would start.\n     * @param  voteStart_ The clock value at which voting would start, inclusively.\n     * @return The clock value at which voting would end, inclusively.\n     */\n    function _getVoteEnd(uint16 voteStart_) internal view returns (uint16) {\n        unchecked {\n            return voteStart_ + _votingPeriod();\n        }\n    }\n\n    /**\n     * @dev    Returns the ballot digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  proposalId_ The unique proposal ID being voted on.\n     * @param  support_    The type of support to cast for the proposal.\n     * @return The digest to be signed.\n     */\n    function _getBallotDigest(uint256 proposalId_, uint8 support_) internal view returns (bytes32) {\n        return _getDigest(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId_, support_)));\n    }\n\n    /**\n     * @dev    Returns the ballots digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  proposalIdsHash_ The hash of the list of unique proposal IDs being voted on.\n     * @param  supportListHash_ The hash of the list of support type per proposal IDs to cast.\n     * @return The digest to be signed.\n     */\n    function _getBallotsDigest(bytes32 proposalIdsHash_, bytes32 supportListHash_) internal view returns (bytes32) {\n        return _getDigest(keccak256(abi.encode(BALLOTS_TYPEHASH, proposalIdsHash_, supportListHash_)));\n    }\n\n    /**\n     * @dev    Returns the ballot with reason digest to be signed, via EIP-712,\n     *         given an internal digest (i.e. hash struct).\n     * @param  proposalId_ The unique proposal ID being voted on.\n     * @param  support_    The type of support to cast for the proposal.\n     * @param  reason_     The reason for which the caller casts their vote, if any.\n     * @return The digest to be signed.\n     */\n    function _getBallotWithReasonDigest(\n        uint256 proposalId_,\n        uint8 support_,\n        string calldata reason_\n    ) internal view returns (bytes32) {\n        return\n            _getDigest(\n                keccak256(abi.encode(BALLOT_WITH_REASON_TYPEHASH, proposalId_, support_, keccak256(bytes(reason_))))\n            );\n    }\n\n    /**\n     * @dev    Returns the ballots digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  proposalIdsHash_ The hash of the list of unique proposal IDs being voted on.\n     * @param  supportListHash_ The hash of the list of support type per proposal IDs to cast.\n     * @param  reasonListHash_  The hash of the list of reason per proposal IDs to cast.\n     * @return The digest to be signed.\n     */\n    function _getBallotsWithReasonDigest(\n        bytes32 proposalIdsHash_,\n        bytes32 supportListHash_,\n        bytes32 reasonListHash_\n    ) internal view returns (bytes32) {\n        return\n            _getDigest(\n                keccak256(abi.encode(BALLOTS_WITH_REASON_TYPEHASH, proposalIdsHash_, supportListHash_, reasonListHash_))\n            );\n    }\n\n    /**\n     * @dev    Returns the hash of the reason list to be used in the ballots digest.\n     * @param  reasonList_ The list of reasons to hash.\n     * @return The hash of the reason list.\n     */\n    function _getReasonListHash(string[] calldata reasonList_) internal pure returns (bytes32) {\n        uint256 reasonListLength_ = reasonList_.length;\n        bytes32[] memory reasonListBytes_ = new bytes32[](reasonListLength_);\n\n        for (uint256 index_; index_ < reasonListLength_; ++index_) {\n            reasonListBytes_[index_] = keccak256(bytes(reasonList_[index_]));\n        }\n\n        return keccak256(abi.encodePacked(reasonListBytes_));\n    }\n\n    /**\n     * @dev    Returns the unique identifier for the proposal if it were created at this exact moment.\n     * @param  callData_ The single call data used to call this governor upon execution of a proposal.\n     * @return The unique identifier for the proposal.\n     */\n    function _hashProposal(bytes memory callData_) internal view returns (uint256) {\n        return _hashProposal(callData_, _voteStart());\n    }\n\n    /**\n     * @dev    Returns the unique identifier for the proposal if it were to have a given vote start timepoint.\n     * @param  callData_  The single call data used to call this governor upon execution of a proposal.\n     * @param  voteStart_ The clock value at which voting would start, inclusively.\n     * @return The unique identifier for the proposal.\n     */\n    function _hashProposal(bytes memory callData_, uint16 voteStart_) internal view returns (uint256) {\n        return uint256(keccak256(abi.encode(callData_, voteStart_, address(this))));\n    }\n\n    /// @dev Reverts if the caller is not the contract itself.\n    function _revertIfNotSelf() internal view {\n        if (msg.sender != address(this)) revert NotSelf();\n    }\n\n    /// @dev Returns the number of clock values that must elapse before voting begins for a newly created proposal.\n    function _votingDelay() internal view virtual returns (uint16);\n\n    /// @dev Returns the number of clock values between the vote start and vote end.\n    function _votingPeriod() internal view virtual returns (uint16);\n\n    /**\n     * @dev   All proposals target this contract itself, and must call one of the listed functions to be valid.\n     * @param callData_ The call data to check.\n     */\n    function _revertIfInvalidCalldata(bytes memory callData_) internal pure virtual;\n\n    /**\n     * @dev   Reverts if the proposal arguments are invalid.\n     * @param targets_   An array of addresses that will be called upon the execution.\n     * @param values_    An array of ETH amounts that will be sent to each respective target upon execution.\n     * @param callDatas_ An array of call data used to call each respective target upon execution.\n     */\n    function _revertIfInvalidProposal(\n        address[] memory targets_,\n        uint256[] memory values_,\n        bytes[] memory callDatas_\n    ) internal view {\n        if (targets_.length != 1) revert InvalidTargetsLength();\n        if (targets_[0] != address(this)) revert InvalidTarget();\n\n        if (values_.length != 1) revert InvalidValuesLength();\n        if (values_[0] != 0) revert InvalidValue();\n\n        if (callDatas_.length != 1) revert InvalidCallDatasLength();\n\n        _revertIfInvalidCalldata(callDatas_[0]);\n    }\n}\n"
      },
      "lib/ttg/src/interfaces/IPowerToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IEpochBasedInflationaryVoteToken } from \"../abstract/interfaces/IEpochBasedInflationaryVoteToken.sol\";\n\n/**\n * @title  An instance of an EpochBasedInflationaryVoteToken delegating control to a Standard Governor,\n *         and enabling auctioning of the unowned inflated supply.\n * @author M^0 Labs\n */\ninterface IPowerToken is IEpochBasedInflationaryVoteToken {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when `buyer` has bought `amount` tokens from the auction, as a total cash token value of `cost`.\n     * @param  buyer  The address of account that bought tokens from the auction.\n     * @param  amount The amount of tokens bought.\n     * @param  cost   The total cash token cost of the purchase.\n     */\n    event Buy(address indexed buyer, uint240 amount, uint256 cost);\n\n    /**\n     * @notice Emitted when the cash token is queued to become `nextCashToken` at the start of epoch `startingEpoch`.\n     * @param  startingEpoch The epoch number as a clock value in which the new cash token takes effect.\n     * @param  nextCashToken The address of the cash token taking effect at `startingEpoch`.\n     */\n    event NextCashTokenSet(uint16 indexed startingEpoch, address indexed nextCashToken);\n\n    /**\n     * @notice Emitted in the constructor at deployment.\n     * @param  tagline The tagline of the contract.\n     */\n    event Tagline(string tagline);\n\n    /**\n     * @notice Emitted when the target supply is queued to become `targetSupply` at the start of epoch `targetEpoch`.\n     * @param  targetEpoch  The epoch number as a clock value in which the new target supply takes effect.\n     * @param  targetSupply The target supply taking effect at `startingEpoch`.\n     */\n    event TargetSupplyInflated(uint16 indexed targetEpoch, uint240 indexed targetSupply);\n\n    /* ============ Custom Errors ============ */\n\n    /// @notice Revert message when the total supply of the bootstrap token is larger than `type(uint240).max`.\n    error BootstrapSupplyTooLarge();\n\n    /// @notice Revert message when the total supply of the bootstrap token is 0.\n    error BootstrapSupplyZero();\n\n    /**\n     * @notice Revert message when the amount available for auction is less than the minimum requested to buy.\n     * @param  amountToAuction    The amount available for auction.\n     * @param  minAmountRequested The minimum amount that was requested to buy.\n     */\n    error InsufficientAuctionSupply(uint240 amountToAuction, uint240 minAmountRequested);\n\n    /// @notice Revert message when the Bootstrap Token specified in the constructor is address(0).\n    error InvalidBootstrapTokenAddress();\n\n    /// @notice Revert message when the Cash Token specified in the constructor is address(0).\n    error InvalidCashTokenAddress();\n\n    /// @notice Revert message when the Standard Governor specified in the constructor is address(0).\n    error InvalidStandardGovernorAddress();\n\n    /// @notice Revert message when the Vault specified in the constructor is address(0).\n    error InvalidVaultAddress();\n\n    /// @notice Revert message when the caller is not the Standard Governor.\n    error NotStandardGovernor();\n\n    /// @notice Revert message when a token transferFrom fails.\n    error TransferFromFailed();\n\n    /// @notice Revert message when auction calculations use zero as denominator.\n    error DivisionByZero();\n\n    /// @notice Revert message when the buy order has expired using epoch-based expiration clock.\n    error ExpiredBuyOrder();\n\n    /// @notice Revert message when the buy order has zero maximum and minimum amounts.\n    error ZeroPurchaseAmount();\n\n    /**\n     * @notice Revert message when trying to sync to an epoch that is before the bootstrap epoch.\n     * @param  bootstrapEpoch The bootstrap epoch.\n     * @param  epoch          The epoch attempting to be synced to, not inclusively.\n     */\n    error SyncBeforeBootstrap(uint16 bootstrapEpoch, uint16 epoch);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Allows a caller to buy `amount` tokens from the auction.\n     * @param  minAmount   The minimum amount of tokens the caller is interested in buying.\n     * @param  maxAmount   The maximum amount of tokens the caller is interested in buying.\n     * @param  destination The address of the account to send the bought tokens.\n     * @param  expiryEpoch The epoch number at the end of which the buy order expires.\n     * @return amount      The amount of token bought.\n     * @return cost        The total cash token cost of the purchase.\n     */\n    function buy(\n        uint256 minAmount,\n        uint256 maxAmount,\n        address destination,\n        uint16 expiryEpoch\n    ) external returns (uint240 amount, uint256 cost);\n\n    /// @notice Marks the next voting epoch as targeted for inflation.\n    function markNextVotingEpochAsActive() external;\n\n    /**\n     * @notice Marks `delegatee` as having participated in the current epoch, thus receiving voting power inflation.\n     * @param  delegatee The address of the account being marked as having participated.\n     */\n    function markParticipation(address delegatee) external;\n\n    /**\n     * @notice Queues the cash token that will take effect from the next epoch onward.\n     * @param  nextCashToken The address of the cash token taking effect from the next epoch onward.\n     */\n    function setNextCashToken(address nextCashToken) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the amount of tokens that can be bought in the auction.\n    function amountToAuction() external view returns (uint240);\n\n    /// @notice Returns the epoch from which token balances and voting powers are bootstrapped.\n    function bootstrapEpoch() external view returns (uint16);\n\n    /// @notice Returns the address of the token in which token balances and voting powers are bootstrapped.\n    function bootstrapToken() external view returns (address);\n\n    /// @notice Returns the address of the cash token required to buy from the token auction.\n    function cashToken() external view returns (address);\n\n    /**\n     * @notice Returns the total cost, in cash token, of purchasing `amount` tokens from the auction.\n     * @param  amount Some amount of tokens.\n     * @return The total cost, in cash token, of `amount` tokens.\n     */\n    function getCost(uint256 amount) external view returns (uint256);\n\n    /// @notice Returns the address of the Standard Governor.\n    function standardGovernor() external view returns (address);\n\n    /// @notice Returns the target supply, which helps determine the amount of tokens up for auction.\n    function targetSupply() external view returns (uint256);\n\n    /// @notice Returns the address of the Vault.\n    function vault() external view returns (address);\n\n    /// @notice Returns the initial supply of the token.\n    function INITIAL_SUPPLY() external pure returns (uint240);\n}\n"
      },
      "lib/ttg/src/interfaces/IRegistrar.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC6372 } from \"../abstract/interfaces/IERC6372.sol\";\n\n/**\n * @title  A book of record of TTG-specific contracts and arbitrary key-value pairs and lists.\n * @author M^0 Labs\n */\ninterface IRegistrar is IERC6372 {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when `account` is added to `list`.\n     * @param  list    The key for the list.\n     * @param  account The address of the added account.\n     */\n    event AddressAddedToList(bytes32 indexed list, address indexed account);\n\n    /**\n     * @notice Emitted when `account` is removed from `list`.\n     * @param  list    The key for the list.\n     * @param  account The address of the removed account.\n     */\n    event AddressRemovedFromList(bytes32 indexed list, address indexed account);\n\n    /**\n     * @notice Emitted when `key` is set to `value`.\n     * @param  key   The key.\n     * @param  value The value.\n     */\n    event KeySet(bytes32 indexed key, bytes32 indexed value);\n\n    /* ============ Custom Errors ============ */\n\n    /// @notice Revert message when the Emergency Governor Deployer retrieved in the constructor is address(0).\n    error InvalidEmergencyGovernorDeployerAddress();\n\n    /// @notice Revert message when the Power Token Deployer retrieved in the constructor is address(0).\n    error InvalidPowerTokenDeployerAddress();\n\n    /// @notice Revert message when the Standard Governor Deployer retrieved in the constructor is address(0).\n    error InvalidStandardGovernorDeployerAddress();\n\n    /// @notice Revert message when the Vault retrieved in the constructor is address(0).\n    error InvalidVaultAddress();\n\n    /// @notice Revert message when the Vote Token retrieved in the constructor is address(0).\n    error InvalidVoteTokenAddress();\n\n    /// @notice Revert message when the Zero Governor specified in the constructor is address(0).\n    error InvalidZeroGovernorAddress();\n\n    /// @notice Revert message when the caller is not the Standard Governor nor the Emergency Governor.\n    error NotStandardOrEmergencyGovernor();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Adds `account` to `list`.\n     * @param  list    The key for some list.\n     * @param  account The address of some account to be added.\n     */\n    function addToList(bytes32 list, address account) external;\n\n    /**\n     * @notice Removes `account` from `list`.\n     * @param  list    The key for some list.\n     * @param  account The address of some account to be removed.\n     */\n    function removeFromList(bytes32 list, address account) external;\n\n    /**\n     * @notice Sets `key` to `value`.\n     * @param  key   Some key.\n     * @param  value Some value.\n     */\n    function setKey(bytes32 key, bytes32 value) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the starting timestamp of Epoch 1.\n    function clockStartingTimestamp() external pure returns (uint256);\n\n    /// @notice Returns the period/duration, in seconds, of an epoch.\n    function clockPeriod() external pure returns (uint256);\n\n    /**\n     * @notice Returns the value of `key`.\n     * @param  key Some key.\n     * @return Some value.\n     */\n    function get(bytes32 key) external view returns (bytes32);\n\n    /**\n     * @notice Returns the values of `keys` respectively.\n     * @param  keys Some keys.\n     * @return Some values.\n     */\n    function get(bytes32[] calldata keys) external view returns (bytes32[] memory);\n\n    /**\n     * @notice Returns whether `list` contains `account`.\n     * @param  list    The key for some list.\n     * @param  account The address of some account.\n     * @return Whether `list` contains `account`.\n     */\n    function listContains(bytes32 list, address account) external view returns (bool);\n\n    /**\n     * @notice Returns whether `list` contains all specified accounts.\n     * @param  list     The key for some list.\n     * @param  accounts An array of addressed of some accounts.\n     * @return Whether `list` contains all specified accounts.\n     */\n    function listContains(bytes32 list, address[] calldata accounts) external view returns (bool);\n\n    /// @notice Returns the address of the Emergency Governor.\n    function emergencyGovernor() external view returns (address);\n\n    /// @notice Returns the address of the Emergency Governor Deployer.\n    function emergencyGovernorDeployer() external view returns (address);\n\n    /// @notice Returns the address of the Power Token.\n    function powerToken() external view returns (address);\n\n    /// @notice Returns the address of the Power Token Deployer.\n    function powerTokenDeployer() external view returns (address);\n\n    /// @notice Returns the address of the Standard Governor.\n    function standardGovernor() external view returns (address);\n\n    /// @notice Returns the address of the Standard Governor Deployer.\n    function standardGovernorDeployer() external view returns (address);\n\n    /// @notice Returns the address of the Vault.\n    function vault() external view returns (address);\n\n    /// @notice Returns the address of the Zero Governor.\n    function zeroGovernor() external view returns (address);\n\n    /// @notice Returns the address of the Zero Token.\n    function zeroToken() external view returns (address);\n}\n"
      },
      "lib/ttg/src/interfaces/IStandardGovernor.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IBatchGovernor } from \"../abstract/interfaces/IBatchGovernor.sol\";\n\n/**\n * @title  An instance of a BatchGovernor with a unique and limited set of possible proposals with proposal fees.\n * @author M^0 Labs\n */\ninterface IStandardGovernor is IBatchGovernor {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when the cash token is set to `cashToken`.\n     * @param  cashToken The address of the cash token taking effect.\n     */\n    event CashTokenSet(address indexed cashToken);\n\n    /**\n     * @notice Emitted when `voter` has voted on all the proposals in the current epoch `currentEpoch`.\n     * @param  voter        The address of the account voting.\n     * @param  currentEpoch The current epoch number as a clock value.\n     */\n    event HasVotedOnAllProposals(address indexed voter, uint256 indexed currentEpoch);\n\n    /**\n     * @notice Emitted when the proposal fee for the proposal, with identifier `proposalFee`, is sent to the vault.\n     * @param  proposalId The unique identifier of the proposal.\n     * @param  cashToken  The address of the cash token for this particular proposal fee.\n     * @param  amount     The amount of cash token of the proposal fee.\n     */\n    event ProposalFeeSentToVault(uint256 indexed proposalId, address indexed cashToken, uint256 amount);\n\n    /**\n     * @notice Emitted when the proposal fee is set to `proposalFee`.\n     * @param  proposalFee The amount of cash token required onwards to create proposals.\n     */\n    event ProposalFeeSet(uint256 proposalFee);\n\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when the proposal fee for a yet defeated or yet expired proposal is trying to be moved.\n     * @param  state The current state of the proposal.\n     */\n    error FeeNotDestinedForVault(ProposalState state);\n\n    /// @notice Revert message when the Cash Token specified in the constructor is address(0).\n    error InvalidCashTokenAddress();\n\n    /// @notice Revert message when the Emergency Governor specified in the constructor is address(0).\n    error InvalidEmergencyGovernorAddress();\n\n    /// @notice Revert message when the Registrar specified in the constructor is address(0).\n    error InvalidRegistrarAddress();\n\n    /// @notice Revert message when the Vault specified in the constructor is address(0).\n    error InvalidVaultAddress();\n\n    /// @notice Revert message when the Zero Governor specified in the constructor is address(0).\n    error InvalidZeroGovernorAddress();\n\n    /// @notice Revert message when the Zero Token specified in the constructor is address(0).\n    error InvalidZeroTokenAddress();\n\n    /// @notice Revert message when proposal fee trying to be moved to the vault is 0.\n    error NoFeeToSend();\n\n    /// @notice Revert message when the caller is not this contract itself nor the Emergency Governor.\n    error NotSelfOrEmergencyGovernor();\n\n    /// @notice Revert message when the caller is not the Zero Governor.\n    error NotZeroGovernor();\n\n    /// @notice Revert message when a token transfer, from this contract, fails.\n    error TransferFailed();\n\n    /// @notice Revert message when a token transferFrom fails.\n    error TransferFromFailed();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Sends the proposal fee for proposal `proposalId` to the vault, if it is Defeated or Expired.\n     * @param  proposalId The unique identifier of the proposal.\n     */\n    function sendProposalFeeToVault(uint256 proposalId) external;\n\n    /**\n     * @notice Set the cash token and proposal fee to be used to create proposals going forward.\n     * @param  newCashToken   The address of the new cash token.\n     * @param  newProposalFee The amount of cash token required onwards to create proposals.\n     */\n    function setCashToken(address newCashToken, uint256 newProposalFee) external;\n\n    /* ============ Proposal Functions ============ */\n\n    /**\n     * @notice One of the valid proposals. Adds `account` to `list` at the Registrar.\n     * @param  list    The key for some list.\n     * @param  account The address of some account to be added.\n     */\n    function addToList(bytes32 list, address account) external;\n\n    /**\n     * @notice One of the valid proposals. Removes `account` to `list` at the Registrar.\n     * @param  list    The key for some list.\n     * @param  account The address of some account to be removed.\n     */\n    function removeFromList(bytes32 list, address account) external;\n\n    /**\n     * @notice One of the valid proposals. Removes `accountToRemove` and adds `accountToAdd` to `list` at the Registrar.\n     * @param  list            The key for some list.\n     * @param  accountToRemove The address of some account to be removed.\n     * @param  accountToAdd    The address of some account to be added.\n     */\n    function removeFromAndAddToList(bytes32 list, address accountToRemove, address accountToAdd) external;\n\n    /**\n     * @notice One of the valid proposals. Sets `key` to `value` at the Registrar.\n     * @param  key   Some key.\n     * @param  value Some value.\n     */\n    function setKey(bytes32 key, bytes32 value) external;\n\n    /**\n     * @notice One of the valid proposals. Sets the proposal fee of the Standard Governor.\n     * @param  newProposalFee The new proposal fee.\n     */\n    function setProposalFee(uint256 newProposalFee) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the required amount of cashToken it costs an account to create a proposal.\n    function proposalFee() external view returns (uint256);\n\n    /**\n     * @notice Returns all the proposal details for a proposal with identifier `proposalId`.\n     * @param  proposalId The unique identifier of the proposal.\n     * @return voteStart  The first clock value when voting on the proposal is allowed.\n     * @return voteEnd    The last clock value when voting on the proposal is allowed.\n     * @return state      The state of the proposal.\n     * @return noVotes    The amount of votes cast against the proposal.\n     * @return yesVotes   The amount of votes cast for the proposal.\n     * @return proposer   The address of the account that created the proposal.\n     * @return quorum     The number of votes required to meet quorum.\n     */\n    function getProposal(\n        uint256 proposalId\n    )\n        external\n        view\n        returns (\n            uint48 voteStart,\n            uint48 voteEnd,\n            ProposalState state,\n            uint256 noVotes,\n            uint256 yesVotes,\n            address proposer,\n            uint256 quorum\n        );\n\n    /**\n     * @notice Returns the proposal fee information.\n     * @param  proposalId The unique identifier of the proposal.\n     * @return cashToken  The address of the cash token for this particular proposal fee.\n     * @return amount     The amount of cash token of the proposal fee.\n     */\n    function getProposalFee(uint256 proposalId) external view returns (address cashToken, uint256 amount);\n\n    /// @notice Returns the maximum amount of Zero Token that can be rewarded to all vote casters per active epoch.\n    function maxTotalZeroRewardPerActiveEpoch() external view returns (uint256);\n\n    /**\n     * @notice Returns the number of proposals at epoch `epoch`.\n     * @param  epoch The epoch as a clock value.\n     * @return The number of proposals at epoch `epoch`.\n     */\n    function numberOfProposalsAt(uint256 epoch) external view returns (uint256);\n\n    /**\n     * @notice Returns the number of proposals that were voted on at `epoch`.\n     * @param  voter The address of some account.\n     * @param  epoch The epoch as a clock value.\n     * @return The number of proposals at `epoch`.\n     */\n    function numberOfProposalsVotedOnAt(address voter, uint256 epoch) external view returns (uint256);\n\n    /**\n     * @notice Returns whether `voter` has voted on all proposals in `epoch`.\n     * @param  voter The address of some account.\n     * @param  epoch The epoch as a clock value.\n     * @return Whether `voter` has voted on all proposals in `epoch`.\n     */\n    function hasVotedOnAllProposals(address voter, uint256 epoch) external view returns (bool);\n\n    /// @notice Returns the address of the Cash Token.\n    function cashToken() external view returns (address);\n\n    /// @notice Returns the address of the Emergency Governor.\n    function emergencyGovernor() external view returns (address);\n\n    /// @notice Returns the address of the Registrar.\n    function registrar() external view returns (address);\n\n    /// @notice Returns the address of the Vault.\n    function vault() external view returns (address);\n\n    /// @notice Returns the address of the Zero Governor.\n    function zeroGovernor() external view returns (address);\n\n    /// @notice Returns the address of the Zero Token.\n    function zeroToken() external view returns (address);\n}\n"
      },
      "lib/ttg/src/interfaces/IZeroToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IEpochBasedVoteToken } from \"../abstract/interfaces/IEpochBasedVoteToken.sol\";\n\n/**\n * @title  An instance of an EpochBasedVoteToken delegating minting control to a Standard Governor,\n *         and enabling range queries for past balances, voting powers, delegations, and  total supplies.\n * @author M^0 Labs\n */\ninterface IZeroToken is IEpochBasedVoteToken {\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when the length of some accounts array does not equal the length of some balances array.\n     * @param  accountsLength The length of the accounts array.\n     * @param  balancesLength The length of the balances array.\n     */\n    error ArrayLengthMismatch(uint256 accountsLength, uint256 balancesLength);\n\n    /// @notice Revert message when the Standard Governor Deployer specified in the constructor is address(0).\n    error InvalidStandardGovernorDeployerAddress();\n\n    /// @notice Revert message when the caller is not the Standard Governor.\n    error NotStandardGovernor();\n\n    /// @notice Revert message when the start of an inclusive range query is larger than the end.\n    error StartEpochAfterEndEpoch();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Mints `amount` token to `recipient`.\n     * @param  recipient The address of the account receiving minted token.\n     * @param  amount    The amount of token to mint.\n     */\n    function mint(address recipient, uint256 amount) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns an array of token balances of `account`\n     *         between `startEpoch` and `endEpoch` past inclusive clocks.\n     * @param  account    The address of some account.\n     * @param  startEpoch The starting epoch number as a clock value.\n     * @param  endEpoch   The ending epoch number as a clock value.\n     * @return An array of token balances, each relating to an epoch in the inclusive range.\n     */\n    function pastBalancesOf(\n        address account,\n        uint256 startEpoch,\n        uint256 endEpoch\n    ) external view returns (uint256[] memory);\n\n    /**\n     * @notice Returns an array of total token supplies between `startEpoch` and `endEpoch` clocks inclusively.\n     * @param  startEpoch The starting epoch number as a clock value.\n     * @param  endEpoch   The ending epoch number as a clock value.\n     * @return An array of total supplies, each relating to an epoch in the inclusive range.\n     */\n    function pastTotalSupplies(uint256 startEpoch, uint256 endEpoch) external view returns (uint256[] memory);\n\n    /// @notice Returns the address of the Standard Governor.\n    function standardGovernor() external view returns (address);\n\n    /// @notice Returns the address of the Standard Governor Deployer.\n    function standardGovernorDeployer() external view returns (address);\n}\n"
      },
      "lib/ttg/lib/erc20-helper/src/interfaces/IERC20Like.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.7;\n\n/// @title Interface of the ERC20 standard as needed by ERC20Helper.\ninterface IERC20Like {\n\n    function approve(address spender_, uint256 amount_) external returns (bool success_);\n\n    function transfer(address recipient_, uint256 amount_) external returns (bool success_);\n\n    function transferFrom(address owner_, address recipient_, uint256 amount_) external returns (bool success_);\n\n}\n"
      },
      "lib/ttg/lib/common/src/interfaces/IERC712.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  Typed structured data hashing and signing via EIP-712.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-712: https://eips.ethereum.org/EIPS/eip-712\n */\ninterface IERC712 {\n    /* ============ Custom Errors ============ */\n\n    /// @notice Revert message when an invalid signature is detected.\n    error InvalidSignature();\n\n    /// @notice Revert message when a signature with invalid length is detected.\n    error InvalidSignatureLength();\n\n    /// @notice Revert message when the S portion of a signature is invalid.\n    error InvalidSignatureS();\n\n    /// @notice Revert message when the V portion of a signature is invalid.\n    error InvalidSignatureV();\n\n    /**\n     * @notice Revert message when a signature is being used beyond its deadline (i.e. expiry).\n     * @param  deadline  The deadline of the signature.\n     * @param  timestamp The current timestamp.\n     */\n    error SignatureExpired(uint256 deadline, uint256 timestamp);\n\n    /// @notice Revert message when a recovered signer does not match the account being purported to have signed.\n    error SignerMismatch();\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the EIP712 domain separator used in the encoding of a signed digest.\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "lib/ttg/src/abstract/interfaces/IERC6372.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  Contract clock properties.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-6372: https://eips.ethereum.org/EIPS/eip-6372\n */\ninterface IERC6372 {\n    /// @notice Returns a machine-readable string description of the clock the contract is operating on.\n    function CLOCK_MODE() external view returns (string memory);\n\n    /// @notice Returns the current timepoint according to the mode the contract is operating on.\n    function clock() external view returns (uint48);\n}\n"
      },
      "lib/ttg/lib/common/src/ERC712Extended.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC712 } from \"./interfaces/IERC712.sol\";\nimport { IERC712Extended } from \"./interfaces/IERC712Extended.sol\";\n\nimport { SignatureChecker } from \"./libs/SignatureChecker.sol\";\n\n/**\n * @title  Typed structured data hashing and signing via EIP-712, extended by EIP-5267.\n * @author M^0 Labs\n * @dev    An abstract implementation to satisfy EIP-712: https://eips.ethereum.org/EIPS/eip-712\n */\nabstract contract ERC712Extended is IERC712Extended {\n    /* ============ Variables ============ */\n\n    /// @dev keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")\n    bytes32 internal constant _EIP712_DOMAIN_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\n\n    /// @dev keccak256(\"1\")\n    bytes32 internal constant _EIP712_VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;\n\n    /// @dev Initial Chain ID set at deployment.\n    uint256 internal immutable _INITIAL_CHAIN_ID;\n\n    /// @dev Initial EIP-712 domain separator set at deployment.\n    bytes32 internal immutable _INITIAL_DOMAIN_SEPARATOR;\n\n    /// @dev The name of the contract.\n    string internal _name;\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Constructs the EIP-712 domain separator.\n     * @param  name_ The name of the contract.\n     */\n    constructor(string memory name_) {\n        _name = name_;\n\n        _INITIAL_CHAIN_ID = block.chainid;\n        _INITIAL_DOMAIN_SEPARATOR = _getDomainSeparator();\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IERC712Extended\n    function eip712Domain()\n        external\n        view\n        virtual\n        returns (\n            bytes1 fields_,\n            string memory name_,\n            string memory version_,\n            uint256 chainId_,\n            address verifyingContract_,\n            bytes32 salt_,\n            uint256[] memory extensions_\n        )\n    {\n        return (\n            hex\"0f\", // 01111\n            _name,\n            \"1\",\n            block.chainid,\n            address(this),\n            bytes32(0),\n            new uint256[](0)\n        );\n    }\n\n    /// @inheritdoc IERC712\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return block.chainid == _INITIAL_CHAIN_ID ? _INITIAL_DOMAIN_SEPARATOR : _getDomainSeparator();\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Computes the EIP-712 domain separator.\n     * @return The EIP-712 domain separator.\n     */\n    function _getDomainSeparator() internal view returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    _EIP712_DOMAIN_HASH,\n                    keccak256(bytes(_name)),\n                    _EIP712_VERSION_HASH,\n                    block.chainid,\n                    address(this)\n                )\n            );\n    }\n\n    /**\n     * @dev    Returns the digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  internalDigest_ The internal digest.\n     * @return The digest to be signed.\n     */\n    function _getDigest(bytes32 internalDigest_) internal view returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR(), internalDigest_));\n    }\n\n    /**\n     * @dev   Revert if the signature is expired.\n     * @param expiry_ Timestamp at which the signature expires or max uint256 for no expiry.\n     */\n    function _revertIfExpired(uint256 expiry_) internal view {\n        if (block.timestamp > expiry_) revert SignatureExpired(expiry_, block.timestamp);\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @dev   We first validate if the signature is a valid ECDSA signature and return early if it is the case.\n     *        Then, we validate if it is a valid ERC-1271 signature, and return early if it is the case.\n     *        If not, we revert with the error from the ECDSA signature validation.\n     * @param signer_    The signer of the signature.\n     * @param digest_    The digest that was signed.\n     * @param signature_ The signature.\n     */\n    function _revertIfInvalidSignature(address signer_, bytes32 digest_, bytes memory signature_) internal view {\n        SignatureChecker.Error error_ = SignatureChecker.validateECDSASignature(signer_, digest_, signature_);\n\n        if (error_ == SignatureChecker.Error.NoError) return;\n\n        if (SignatureChecker.isValidERC1271Signature(signer_, digest_, signature_)) return;\n\n        _revertIfError(error_);\n    }\n\n    /**\n     * @dev    Returns the signer of a signed digest, via EIP-712, and reverts if the signature is invalid.\n     * @param  digest_ The digest that was signed.\n     * @param  v_      v of the signature.\n     * @param  r_      r of the signature.\n     * @param  s_      s of the signature.\n     * @return signer_ The signer of the digest.\n     */\n    function _getSignerAndRevertIfInvalidSignature(\n        bytes32 digest_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) internal pure returns (address signer_) {\n        SignatureChecker.Error error_;\n\n        (error_, signer_) = SignatureChecker.recoverECDSASigner(digest_, v_, r_, s_);\n\n        _revertIfError(error_);\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @param signer_ The signer of the signature.\n     * @param digest_ The digest that was signed.\n     * @param r_      An ECDSA/secp256k1 signature parameter.\n     * @param vs_     An ECDSA/secp256k1 short signature parameter.\n     */\n    function _revertIfInvalidSignature(address signer_, bytes32 digest_, bytes32 r_, bytes32 vs_) internal pure {\n        _revertIfError(SignatureChecker.validateECDSASignature(signer_, digest_, r_, vs_));\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @param signer_ The signer of the signature.\n     * @param digest_ The digest that was signed.\n     * @param v_      v of the signature.\n     * @param r_      r of the signature.\n     * @param s_      s of the signature.\n     */\n    function _revertIfInvalidSignature(\n        address signer_,\n        bytes32 digest_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) internal pure {\n        _revertIfError(SignatureChecker.validateECDSASignature(signer_, digest_, v_, r_, s_));\n    }\n\n    /**\n     * @dev   Revert if error.\n     * @param error_ The SignatureChecker Error enum.\n     */\n    function _revertIfError(SignatureChecker.Error error_) private pure {\n        if (error_ == SignatureChecker.Error.NoError) return;\n        if (error_ == SignatureChecker.Error.InvalidSignature) revert InvalidSignature();\n        if (error_ == SignatureChecker.Error.InvalidSignatureLength) revert InvalidSignatureLength();\n        if (error_ == SignatureChecker.Error.InvalidSignatureS) revert InvalidSignatureS();\n        if (error_ == SignatureChecker.Error.InvalidSignatureV) revert InvalidSignatureV();\n        if (error_ == SignatureChecker.Error.SignerMismatch) revert SignerMismatch();\n\n        revert InvalidSignature();\n    }\n}\n"
      },
      "lib/ttg/src/libs/PureEpochs.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @notice Defines epochs as periods away from STARTING_TIMESTAMP timestamp.\n * @author M^0 Labs\n * @dev    Provides a `uint16` epoch clock value.\n */\nlibrary PureEpochs {\n    /* ============ Variables ============ */\n\n    /// @notice The timestamp of the start of Epoch 1.\n    uint40 internal constant STARTING_TIMESTAMP = 1713099600;\n\n    /// @notice The approximate target of seconds an epoch should endure.\n    uint40 internal constant EPOCH_PERIOD = 1296000;\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /// @dev Returns the current epoch number.\n    function currentEpoch() internal view returns (uint16) {\n        return uint16(((block.timestamp - STARTING_TIMESTAMP) / EPOCH_PERIOD) + 1);\n    }\n\n    /// @dev Returns the remaining time in the current epoch.\n    function timeRemainingInCurrentEpoch() internal view returns (uint40) {\n        return STARTING_TIMESTAMP + (currentEpoch() * EPOCH_PERIOD) - uint40(block.timestamp);\n    }\n\n    function clockMode() internal pure returns (string memory) {\n        return \"mode=epoch&epochUnderlyingSource=blockTimestamp&epochStartingTimestamp=1713099600&epochPeriod=1296000\";\n    }\n}\n"
      },
      "lib/ttg/src/abstract/interfaces/IBatchGovernor.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IGovernor } from \"./IGovernor.sol\";\n\n/**\n * @title  Extension for Governor with specialized strict proposal parameters, vote batching, and an epoch clock.\n * @author M^0 Labs\n */\ninterface IBatchGovernor is IGovernor {\n    /* ============ Enums ============ */\n\n    /**\n     * @notice The type of support to cast for a proposal.\n     * @param  No  The voter does not support the proposal.\n     * @param  Yes The voter supports the proposal.\n     */\n    enum VoteType {\n        No,\n        Yes\n    }\n\n    /* ============ Custom Errors ============ */\n\n    /// @notice Revert message when a voter is trying to vote on a proposal they already voted on.\n    error AlreadyVoted();\n\n    /// @notice Revert message when input arrays do not match in length.\n    error ArrayLengthMismatch(uint256 length1, uint256 length2);\n\n    /// @notice Revert message when the proposal IDs array is empty.\n    error EmptyProposalIdsArray();\n\n    /**\n     * @notice Revert message when execution of a proposal fails.\n     * @param  data The revert data returned due to the failed execution.\n     */\n    error ExecutionFailed(bytes data);\n\n    /// @notice Revert message when a proposal's call data is not specifically supported.\n    error InvalidCallData();\n\n    /// @notice Revert message when a proposal's call data array is not of length 1.\n    error InvalidCallDatasLength();\n\n    /// @notice Revert message when a proposal target is not this governor itself.\n    error InvalidTarget();\n\n    /// @notice Revert message when a proposal's targets array is not of length 1.\n    error InvalidTargetsLength();\n\n    /// @notice Revert message when a proposal value is not 0 ETH.\n    error InvalidValue();\n\n    /// @notice Revert message when a proposal's values array is not of length 1.\n    error InvalidValuesLength();\n\n    /// @notice Revert message when a an invalid vote start is detected.\n    error InvalidVoteStart();\n\n    /// @notice Revert message when the vote token specified in the constructor is address(0).\n    error InvalidVoteTokenAddress();\n\n    /// @notice Revert message when the caller of a governance-controlled function is not this governor itself.\n    error NotSelf();\n\n    /// @notice Revert message when the proposal information provided cannot be executed.\n    error ProposalCannotBeExecuted();\n\n    /// @notice Revert message when the proposal does not exist.\n    error ProposalDoesNotExist();\n\n    /// @notice Revert message when the proposal already exists.\n    error ProposalExists();\n\n    /**\n     * @notice Revert message when voting on a proposal that is not in an active state (i.e. not collecting votes).\n     * @param  state The current state of the proposal.\n     */\n    error ProposalInactive(ProposalState state);\n\n    /// @notice Revert message when voting on a proposal with a zero voting weight.\n    error ZeroVotingPower();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Allows the caller to cast votes on multiple proposals.\n     * @param  proposalIds The list of unique proposal IDs being voted on.\n     * @param  supportList The list of support type per proposal IDs to cast.\n     * @return weight      The number of votes cast for each proposal (the same for all of them).\n     */\n    function castVotes(uint256[] calldata proposalIds, uint8[] calldata supportList) external returns (uint256 weight);\n\n    /**\n     * @notice Allows a signer to cast votes on multiple proposals via an ECDSA secp256k1 signature.\n     * @param  proposalIds The list of unique proposal IDs being voted on.\n     * @param  supportList The list of support type per proposal IDs to cast.\n     * @param  v           An ECDSA secp256k1 signature parameter.\n     * @param  r           An ECDSA secp256k1 signature parameter.\n     * @param  s           An ECDSA secp256k1 signature parameter.\n     * @return weight      The number of votes cast for each proposal (the same for all of them).\n     */\n    function castVotesBySig(\n        uint256[] calldata proposalIds,\n        uint8[] calldata supportList,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows a signer to cast votes on multiple proposals via an arbitrary signature.\n     * @param  voter       The address of the account casting the votes.\n     * @param  proposalIds The list of unique proposal IDs being voted on.\n     * @param  supportList The list of support type per proposal IDs to cast.\n     * @param  signature   An arbitrary signature\n     * @return weight      The number of votes cast for each proposal (the same for all of them).\n     */\n    function castVotesBySig(\n        address voter,\n        uint256[] calldata proposalIds,\n        uint8[] calldata supportList,\n        bytes memory signature\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows the caller to cast votes with reason on multiple proposals.\n     * @param  proposalIds The list of unique proposal IDs being voted on.\n     * @param  supportList The list of support type per proposal IDs to cast.\n     * @param  reasonList  The list of reason per proposal IDs to cast.\n     * @return weight      The number of votes cast for each proposal (the same for all of them).\n     */\n    function castVotesWithReason(\n        uint256[] calldata proposalIds,\n        uint8[] calldata supportList,\n        string[] calldata reasonList\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows a signer to cast votes with reason on multiple proposals via an ECDSA secp256k1 signature.\n     * @param  proposalIds The list of unique proposal IDs being voted on.\n     * @param  supportList The list of support type per proposal IDs to cast.\n     * @param  reasonList  The list of reason per proposal IDs to cast.\n     * @param  v           An ECDSA secp256k1 signature parameter.\n     * @param  r           An ECDSA secp256k1 signature parameter.\n     * @param  s           An ECDSA secp256k1 signature parameter.\n     * @return weight      The number of votes cast for each proposal (the same for all of them).\n     */\n    function castVotesWithReasonBySig(\n        uint256[] calldata proposalIds,\n        uint8[] calldata supportList,\n        string[] calldata reasonList,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external returns (uint256 weight);\n\n    /**\n     * @notice Allows a signer to cast votes with reason on multiple proposals via an arbitrary signature.\n     * @param  voter       The address of the account casting the votes.\n     * @param  proposalIds The list of unique proposal IDs being voted on.\n     * @param  supportList The list of support type per proposal IDs to cast.\n     * @param  reasonList  The list of reason per proposal IDs to cast.\n     * @param  signature   An arbitrary signature\n     * @return weight      The number of votes cast for each proposal (the same for all of them).\n     */\n    function castVotesWithReasonBySig(\n        address voter,\n        uint256[] calldata proposalIds,\n        uint8[] calldata supportList,\n        string[] calldata reasonList,\n        bytes memory signature\n    ) external returns (uint256 weight);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the ballot digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  proposalId The unique proposal ID being voted on.\n     * @param  support    The type of support to cast for the proposal.\n     * @return The digest to be signed.\n     */\n    function getBallotDigest(uint256 proposalId, uint8 support) external view returns (bytes32);\n\n    /**\n     * @notice Returns the ballots digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  proposalIds The list of unique proposal IDs being voted on.\n     * @param  supportList The list of support type per proposal IDs to cast.\n     * @return The digest to be signed.\n     */\n    function getBallotsDigest(\n        uint256[] calldata proposalIds,\n        uint8[] calldata supportList\n    ) external view returns (bytes32);\n\n    /**\n     * @notice Returns the ballot with reason digest to be signed, via EIP-712,\n     *         given an internal digest (i.e. hash struct).\n     * @param  proposalId The unique proposal ID being voted on.\n     * @param  support    The type of support to cast for the proposal.\n     * @param  reason     The reason for which the caller casts their vote, if any.\n     * @return The digest to be signed.\n     */\n    function getBallotWithReasonDigest(\n        uint256 proposalId,\n        uint8 support,\n        string calldata reason\n    ) external view returns (bytes32);\n\n    /**\n     * @notice Returns the ballots with reason digest to be signed, via EIP-712,\n     *         given an internal digest (i.e. hash struct).\n     * @param  proposalIds The list of unique proposal IDs being voted on.\n     * @param  supportList The list of support type per proposal IDs to cast.\n     * @param  reasonList  The list of reason per proposal IDs to cast.\n     * @return The digest to be signed.\n     */\n    function getBallotsWithReasonDigest(\n        uint256[] calldata proposalIds,\n        uint8[] calldata supportList,\n        string[] calldata reasonList\n    ) external view returns (bytes32);\n\n    /**\n     * @notice Returns the unique identifier for the proposal if it were created at this exact moment.\n     * @param  callData The single call data used to call this governor upon execution of a proposal.\n     * @return The unique identifier for the proposal.\n     */\n    function hashProposal(bytes memory callData) external view returns (uint256);\n\n    /// @notice Returns the EIP-5805 token contact used for determine voting power and total supplies.\n    function voteToken() external view returns (address);\n\n    /// @notice Returns the EIP712 typehash used in the encoding of the digest for `castVotesBySig` function.\n    function BALLOTS_TYPEHASH() external pure returns (bytes32);\n\n    /// @notice Returns the EIP712 typehash used in the encoding of the digest for `castVotesWithReasonBySig` function.\n    function BALLOTS_WITH_REASON_TYPEHASH() external pure returns (bytes32);\n}\n"
      },
      "lib/ttg/src/abstract/interfaces/IEpochBasedVoteToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC20Extended } from \"../../../lib/common/src/interfaces/IERC20Extended.sol\";\n\nimport { IERC5805 } from \"./IERC5805.sol\";\n\n/**\n * @title  Extension for an ERC5805 token that uses epochs as its clock mode and delegation via IERC1271.\n * @author M^0 Labs\n */\ninterface IEpochBasedVoteToken is IERC5805, IERC20Extended {\n    /* ============ Custom Errors ============ */\n\n    /// @notice Revert message when the provided epoch is zero.\n    error EpochZero();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Changes the voting power delegation for `account` to `delegatee`.\n     * @param  account   The purported address of the signing account.\n     * @param  delegatee The address the voting power of `account` will be delegated to.\n     * @param  nonce     The nonce used for the signature.\n     * @param  expiry    The timestamp until which the signature is still valid.\n     * @param  signature A byte array signature.\n     */\n    function delegateBySig(\n        address account,\n        address delegatee,\n        uint256 nonce,\n        uint256 expiry,\n        bytes memory signature\n    ) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  delegatee The address of the delegatee to delegate to.\n     * @param  nonce     The nonce of the account delegating.\n     * @param  expiry    The timestamp until which the signature is still valid.\n     * @return The digest to be signed.\n     */\n    function getDelegationDigest(address delegatee, uint256 nonce, uint256 expiry) external view returns (bytes32);\n\n    /**\n     * @notice Returns the token balance of `account` at a past clock value `epoch`.\n     * @param  account The address of some account.\n     * @param  epoch   The epoch number as a clock value.\n     * @return The token balance `account` at `epoch`.\n     */\n    function pastBalanceOf(address account, uint256 epoch) external view returns (uint256);\n\n    /**\n     * @notice Returns the delegatee of `account` at a past clock value `epoch`.\n     * @param  account The address of some account.\n     * @param  epoch   The epoch number as a clock value.\n     * @return The delegatee of the voting power of `account` at `epoch`.\n     */\n    function pastDelegates(address account, uint256 epoch) external view returns (address);\n\n    /**\n     * @notice Returns the total token supply at a past clock value `epoch`.\n     * @param  epoch The epoch number as a clock value.\n     * @return The total token supply at `epoch`.\n     */\n    function pastTotalSupply(uint256 epoch) external view returns (uint256);\n}\n"
      },
      "lib/ttg/src/abstract/interfaces/IEpochBasedInflationaryVoteToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IEpochBasedVoteToken } from \"./IEpochBasedVoteToken.sol\";\n\n/**\n * @title  Extension for an EpochBasedVoteToken token that allows for inflating tokens and voting power.\n * @author M^0 Labs\n */\ninterface IEpochBasedInflationaryVoteToken is IEpochBasedVoteToken {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when `account` is manually synced.\n     * @param  account The address of an account that is synced.\n     */\n    event Sync(address indexed account);\n\n    /* ============ Custom Errors ============ */\n\n    /// @notice Revert message when trying to mark an account as participated in an epoch where it already participated.\n    error AlreadyParticipated();\n\n    /**\n     * @notice Revert message when the proposed epoch is larger than the current epoch.\n     * @param  currentEpoch The current epoch clock value.\n     * @param  epoch        The handled epoch clock value.\n     */\n    error FutureEpoch(uint16 currentEpoch, uint16 epoch);\n\n    /// @notice Revert message when trying to construct contact with inflation above 100%.\n    error InflationTooHigh();\n\n    /// @notice Revert message when trying to perform an action not allowed outside of designated voting epochs.\n    error NotVoteEpoch();\n\n    /// @notice Revert message when trying to perform an action not allowed during designated voting epochs.\n    error VoteEpoch();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @dev   Syncs `account` so that its balance Snap array in storage, reflects their unrealized inflation.\n     * @param account The address of the account to sync.\n     */\n    function sync(address account) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns whether `delegatee` has participated in voting during clock value `epoch`.\n     * @param  delegatee The address of a delegatee with voting power.\n     * @param  epoch     The epoch number as a clock value.\n     * @return Whether `delegatee` has participated in voting during `epoch`.\n     */\n    function hasParticipatedAt(address delegatee, uint256 epoch) external view returns (bool);\n\n    /// @notice Returns the participation inflation rate used to inflate tokens for participation.\n    function participationInflation() external view returns (uint16);\n\n    /// @notice Returns 100% in basis point, to be used to correctly ascertain the participation inflation rate.\n    function ONE() external pure returns (uint16);\n}\n"
      },
      "lib/ttg/lib/common/src/interfaces/IERC712Extended.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC712 } from \"./IERC712.sol\";\n\n/**\n * @title  EIP-712 extended by EIP-5267.\n * @author M^0 Labs\n * @dev    The additional interface as defined by EIP-5267: https://eips.ethereum.org/EIPS/eip-5267\n */\ninterface IERC712Extended is IERC712 {\n    /* ============ Events ============ */\n\n    /// @notice MAY be emitted to signal that the domain could have changed.\n    event EIP712DomainChanged();\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the fields and values that describe the domain separator used by this contract for EIP-712.\n    function eip712Domain()\n        external\n        view\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        );\n}\n"
      },
      "lib/ttg/lib/common/src/libs/SignatureChecker.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC1271 } from \"../interfaces/IERC1271.sol\";\n\n/**\n * @title  A library to handle ECDSA/secp256k1 and ERC1271 signatures, individually or in arbitrarily in combination.\n * @author M^0 Labs\n */\nlibrary SignatureChecker {\n    /* ============ Enums ============ */\n\n    /**\n     * @notice An enum representing the possible errors that can be emitted during signature validation.\n     * @param  NoError                No error occurred during signature validation.\n     * @param  InvalidSignature       The signature is invalid.\n     * @param  InvalidSignatureLength The signature length is invalid.\n     * @param  InvalidSignatureS      The signature parameter S is invalid.\n     * @param  InvalidSignatureV      The signature parameter V is invalid.\n     * @param  SignerMismatch         The signer does not match the recovered signer.\n     */\n    enum Error {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV,\n        SignerMismatch\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Returns whether a signature is valid (ECDSA/secp256k1 or ERC1271) for a signer and digest.\n     * @dev    Signatures must not be used as unique identifiers since the `ecrecover` EVM opcode\n     *         allows for malleable (non-unique) signatures.\n     *         See https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-4h98-2769-gh6h\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array signature.\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidSignature(address signer, bytes32 digest, bytes memory signature) internal view returns (bool) {\n        return isValidECDSASignature(signer, digest, signature) || isValidERC1271Signature(signer, digest, signature);\n    }\n\n    /**\n     * @dev    Returns whether an ERC1271 signature is valid for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ERC1271 signature.\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidERC1271Signature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal view returns (bool) {\n        (bool success, bytes memory result) = signer.staticcall(\n            abi.encodeCall(IERC1271.isValidSignature, (digest, signature))\n        );\n\n        return\n            success &&\n            result.length >= 32 &&\n            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector);\n    }\n\n    /**\n     * @dev    Decodes an ECDSA/secp256k1 signature from a byte array to standard v, r, and s parameters.\n     * @param  signature A byte array ECDSA/secp256k1 signature.\n     * @return v         An ECDSA/secp256k1 signature parameter.\n     * @return r         An ECDSA/secp256k1 signature parameter.\n     * @return s         An ECDSA/secp256k1 signature parameter.\n     */\n    function decodeECDSASignature(bytes memory signature) internal pure returns (uint8 v, bytes32 r, bytes32 s) {\n        // ecrecover takes the signature parameters, and they can be decoded using assembly.\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := mload(add(signature, 0x20))\n            s := mload(add(signature, 0x40))\n            v := byte(0, mload(add(signature, 0x60)))\n        }\n    }\n\n    /**\n     * @dev    Decodes an ECDSA/secp256k1 short signature as defined by EIP2098\n     *         from a byte array to standard v, r, and s parameters.\n     * @param  signature A byte array ECDSA/secp256k1 short signature.\n     * @return r         An ECDSA/secp256k1 signature parameter.\n     * @return vs        An ECDSA/secp256k1 short signature parameter.\n     */\n    function decodeShortECDSASignature(bytes memory signature) internal pure returns (bytes32 r, bytes32 vs) {\n        // ecrecover takes the signature parameters, and they can be decoded using assembly.\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := mload(add(signature, 0x20))\n            vs := mload(add(signature, 0x40))\n        }\n    }\n\n    /**\n     * @dev    Returns whether an ECDSA/secp256k1 signature is valid for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal pure returns (bool) {\n        if (signature.length == 64) {\n            (bytes32 r, bytes32 vs) = decodeShortECDSASignature(signature);\n            return isValidECDSASignature(signer, digest, r, vs);\n        }\n\n        return validateECDSASignature(signer, digest, signature) == Error.NoError;\n    }\n\n    /**\n     * @dev    Returns whether an ECDSA/secp256k1 short signature is valid for a signer and digest.\n     * @param  signer  The address of the account purported to have signed.\n     * @param  digest  The hash of the data that was signed.\n     * @param  r       An ECDSA/secp256k1 signature parameter.\n     * @param  vs      An ECDSA/secp256k1 short signature parameter.\n     * @return         Whether the signature is valid or not.\n     */\n    function isValidECDSASignature(address signer, bytes32 digest, bytes32 r, bytes32 vs) internal pure returns (bool) {\n        return validateECDSASignature(signer, digest, r, vs) == Error.NoError;\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 signature for some digest.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ECDSA/secp256k1 signature.\n     * @return           An error, if any, that occurred during the signer recovery.\n     * @return           The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(bytes32 digest, bytes memory signature) internal pure returns (Error, address) {\n        if (signature.length != 65) return (Error.InvalidSignatureLength, address(0));\n\n        (uint8 v, bytes32 r, bytes32 s) = decodeECDSASignature(signature);\n\n        return recoverECDSASigner(digest, v, r, s);\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 short signature for some digest.\n     * @dev    See https://eips.ethereum.org/EIPS/eip-2098\n     * @param  digest The hash of the data that was signed.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  vs     An ECDSA/secp256k1 short signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     * @return        The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(bytes32 digest, bytes32 r, bytes32 vs) internal pure returns (Error, address) {\n        unchecked {\n            // We do not check for an overflow here since the shift operation results in 0 or 1.\n            uint8 v = uint8((uint256(vs) >> 255) + 27);\n            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n            return recoverECDSASigner(digest, v, r, s);\n        }\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 signature for some digest.\n     * @param  digest The hash of the data that was signed.\n     * @param  v      An ECDSA/secp256k1 signature parameter.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  s      An ECDSA/secp256k1 signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     * @return signer The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(\n        bytes32 digest,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (Error, address signer) {\n        // Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}.\n        if (uint256(s) > uint256(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0))\n            return (Error.InvalidSignatureS, address(0));\n\n        if (v != 27 && v != 28) return (Error.InvalidSignatureV, address(0));\n\n        signer = ecrecover(digest, v, r, s);\n\n        return (signer == address(0)) ? (Error.InvalidSignature, address(0)) : (Error.NoError, signer);\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 signature for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ERC1271 signature.\n     * @return           An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, signature);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 short signature for a signer and digest.\n     * @param  signer The address of the account purported to have signed.\n     * @param  digest The hash of the data that was signed.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  vs     An ECDSA/secp256k1 short signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, r, vs);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 signature for a signer and digest.\n     * @param  signer The address of the account purported to have signed.\n     * @param  digest The hash of the data that was signed.\n     * @param  v      An ECDSA/secp256k1 signature parameter.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  s      An ECDSA/secp256k1 signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, v, r, s);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error if `signer` is not `recoveredSigner`.\n     * @param  signer          The address of the some signer.\n     * @param  recoveredSigner The address of the some recoveredSigner.\n     * @return                 An error if `signer` is not `recoveredSigner`.\n     */\n    function validateRecoveredSigner(address signer, address recoveredSigner) internal pure returns (Error) {\n        return (signer == recoveredSigner) ? Error.NoError : Error.SignerMismatch;\n    }\n}\n"
      },
      "lib/ttg/lib/common/src/interfaces/IERC20Extended.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC20 } from \"./IERC20.sol\";\nimport { IERC3009 } from \"./IERC3009.sol\";\n\n/**\n * @title  An ERC20 token extended with EIP-2612 permits for signed approvals (via EIP-712\n *         and with EIP-1271 compatibility), and extended with EIP-3009 transfer with authorization (via EIP-712).\n * @author M^0 Labs\n * @dev    The additional interface as defined by EIP-2612: https://eips.ethereum.org/EIPS/eip-2612\n */\ninterface IERC20Extended is IERC20, IERC3009 {\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when spender's allowance is not sufficient.\n     * @param  spender    Address that may be allowed to operate on tokens without being their owner.\n     * @param  allowance  Amount of tokens a `spender` is allowed to operate with.\n     * @param  needed     Minimum amount required to perform a transfer.\n     */\n    error InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @notice Revert message emitted when the transferred amount is insufficient.\n     * @param  amount Amount transferred.\n     */\n    error InsufficientAmount(uint256 amount);\n\n    /**\n     * @notice Revert message emitted when the recipient of a token is invalid.\n     * @param  recipient Address of the invalid recipient.\n     */\n    error InvalidRecipient(address recipient);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Approves `spender` to spend up to `amount` of the token balance of `owner`, via a signature.\n     * @param  owner    The address of the account who's token balance is being approved to be spent by `spender`.\n     * @param  spender  The address of an account allowed to spend on behalf of `owner`.\n     * @param  value    The amount of the allowance being approved.\n     * @param  deadline The last block number where the signature is still valid.\n     * @param  v        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     * @param  r        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     * @param  s        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Approves `spender` to spend up to `amount` of the token balance of `owner`, via a signature.\n     * @param  owner     The address of the account who's token balance is being approved to be spent by `spender`.\n     * @param  spender   The address of an account allowed to spend on behalf of `owner`.\n     * @param  value     The amount of the allowance being approved.\n     * @param  deadline  The last block number where the signature is still valid.\n     * @param  signature An arbitrary signature (EIP-712).\n     */\n    function permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the EIP712 typehash used in the encoding of the digest for the permit function.\n    function PERMIT_TYPEHASH() external view returns (bytes32);\n}\n"
      },
      "lib/ttg/src/abstract/interfaces/IERC5805.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IStatefulERC712 } from \"../../../lib/common/src/interfaces/IStatefulERC712.sol\";\n\nimport { IERC6372 } from \"./IERC6372.sol\";\n\n/**\n * @title  Voting with voting weight tracking and delegation support.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-5805: https://eips.ethereum.org/EIPS/eip-5805\n */\ninterface IERC5805 is IStatefulERC712, IERC6372 {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when `delegator` changes its voting power delegation from `fromDelegatee` to `toDelegatee`.\n     * @param  delegator     The address of the account changing its voting power delegation.\n     * @param  fromDelegatee The previous account the voting power of `delegator` was delegated to.\n     * @param  toDelegatee   The new account the voting power of `delegator` is delegated to.\n     */\n    event DelegateChanged(address indexed delegator, address indexed fromDelegatee, address indexed toDelegatee);\n\n    /**\n     * @notice Emitted when the available voting power of `delegatee` changes from `previousBalance` to `newBalance`.\n     * @param  delegatee       The address of the account whose voting power is changed.\n     * @param  previousBalance The previous voting power of `delegatee`.\n     * @param  newBalance      The new voting power of `delegatee`.\n     */\n    event DelegateVotesChanged(address indexed delegatee, uint256 previousBalance, uint256 newBalance);\n\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when a query for past values is for a timepoint greater or equal to the current clock.\n     * @param  timepoint The timepoint being queried.\n     * @param  clock     The current timepoint.\n     */\n    error NotPastTimepoint(uint48 timepoint, uint48 clock);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Allows a calling account to change its voting power delegation to `delegatee`.\n     * @param  delegatee The address of the account the caller's voting power will be delegated to.\n     */\n    function delegate(address delegatee) external;\n\n    /**\n     * @notice Changes the signing account's voting power delegation to `delegatee`.\n     * @param  delegatee The address of the account the signing account's voting power will be delegated to.\n     * @param  nonce     The nonce of the account delegating.\n     * @param  expiry    The timestamp until which the signature is still valid.\n     * @param  v         A signature parameter.\n     * @param  r         A signature parameter.\n     * @param  s         A signature parameter.\n     */\n    function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the EIP712 typehash used in the encoding of the digest for the delegateBySig function.\n    function DELEGATION_TYPEHASH() external view returns (bytes32);\n\n    /**\n     * @notice Returns the delegatee the voting power of `account` is delegated to.\n     * @param  account The address of the account that can delegate its voting power.\n     * @return The address of the account the voting power of `account` will be delegated to.\n     */\n    function delegates(address account) external view returns (address);\n\n    /**\n     * @notice Returns the total voting power of `account` at a past clock value `timepoint`.\n     * @param  account   The address of some account.\n     * @param  timepoint The point in time, according to the clock mode the contract is operating on.\n     * @return The total voting power of `account` at clock value `timepoint`.\n     */\n    function getPastVotes(address account, uint256 timepoint) external view returns (uint256);\n\n    /**\n     * @notice Returns the total voting power of `account`.\n     * @param  account The address of some account.\n     * @return The total voting power of `account`.\n     */\n    function getVotes(address account) external view returns (uint256);\n}\n"
      },
      "lib/ttg/lib/common/src/interfaces/IERC1271.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  Standard Signature Validation Method for Contracts via EIP-1271.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-1271: https://eips.ethereum.org/EIPS/eip-1271\n */\ninterface IERC1271 {\n    /**\n     * @dev    Returns a specific magic value if the provided signature is valid for the provided digest.\n     * @param  digest     Hash of the data purported to have been signed.\n     * @param  signature  Signature byte array associated with the digest.\n     * @return magicValue Magic value 0x1626ba7e if the signature is valid.\n     */\n    function isValidSignature(bytes32 digest, bytes memory signature) external view returns (bytes4 magicValue);\n}\n"
      },
      "lib/ttg/lib/common/src/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  ERC20 Token Standard.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-20: https://eips.ethereum.org/EIPS/eip-20\n */\ninterface IERC20 {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when `spender` has been approved for `amount` of the token balance of `account`.\n     * @param  account The address of the account.\n     * @param  spender The address of the spender being approved for the allowance.\n     * @param  amount  The amount of the allowance being approved.\n     */\n    event Approval(address indexed account, address indexed spender, uint256 amount);\n\n    /**\n     * @notice Emitted when `amount` tokens is transferred from `sender` to `recipient`.\n     * @param  sender    The address of the sender who's token balance is decremented.\n     * @param  recipient The address of the recipient who's token balance is incremented.\n     * @param  amount    The amount of tokens being transferred.\n     */\n    event Transfer(address indexed sender, address indexed recipient, uint256 amount);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Allows a calling account to approve `spender` to spend up to `amount` of its token balance.\n     * @dev    MUST emit an `Approval` event.\n     * @param  spender The address of the account being allowed to spend up to the allowed amount.\n     * @param  amount  The amount of the allowance being approved.\n     * @return Whether or not the approval was successful.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @notice Allows a calling account to transfer `amount` tokens to `recipient`.\n     * @param  recipient The address of the recipient who's token balance will be incremented.\n     * @param  amount    The amount of tokens being transferred.\n     * @return Whether or not the transfer was successful.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @notice Allows a calling account to transfer `amount` tokens from `sender`, with allowance, to a `recipient`.\n     * @param  sender    The address of the sender who's token balance will be decremented.\n     * @param  recipient The address of the recipient who's token balance will be incremented.\n     * @param  amount    The amount of tokens being transferred.\n     * @return Whether or not the transfer was successful.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the allowance `spender` is allowed to spend on behalf of `account`.\n     * @param  account The address of the account who's token balance `spender` is allowed to spend.\n     * @param  spender The address of an account allowed to spend on behalf of `account`.\n     * @return The amount `spender` can spend on behalf of `account`.\n     */\n    function allowance(address account, address spender) external view returns (uint256);\n\n    /**\n     * @notice Returns the token balance of `account`.\n     * @param  account The address of some account.\n     * @return The token balance of `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /// @notice Returns the number of decimals UIs should assume all amounts have.\n    function decimals() external view returns (uint8);\n\n    /// @notice Returns the name of the contract/token.\n    function name() external view returns (string memory);\n\n    /// @notice Returns the symbol of the token.\n    function symbol() external view returns (string memory);\n\n    /// @notice Returns the current total supply of the token.\n    function totalSupply() external view returns (uint256);\n}\n"
      },
      "lib/ttg/lib/common/src/interfaces/IERC3009.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IStatefulERC712 } from \"./IStatefulERC712.sol\";\n\n/**\n * @title  Transfer via signed authorization following EIP-3009 standard.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-3009: https://eips.ethereum.org/EIPS/eip-3009\n */\ninterface IERC3009 is IStatefulERC712 {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when an authorization has been canceled.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the canceled authorization.\n     */\n    event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce);\n\n    /**\n     * @notice Emitted when an authorization has been used.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the used authorization.\n     */\n    event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);\n\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Emitted when an authorization has already been used.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the used authorization.\n     */\n    error AuthorizationAlreadyUsed(address authorizer, bytes32 nonce);\n\n    /**\n     * @notice Emitted when an authorization is expired.\n     * @param  timestamp   Timestamp at which the transaction was submitted.\n     * @param  validBefore Timestamp before which the authorization would have been valid.\n     */\n    error AuthorizationExpired(uint256 timestamp, uint256 validBefore);\n\n    /**\n     * @notice Emitted when an authorization is not yet valid.\n     * @param  timestamp  Timestamp at which the transaction was submitted.\n     * @param  validAfter Timestamp after which the authorization will be valid.\n     */\n    error AuthorizationNotYetValid(uint256 timestamp, uint256 validAfter);\n\n    /**\n     * @notice Emitted when the caller of `receiveWithAuthorization` is not the payee.\n     * @param  caller Caller's address.\n     * @param  payee  Payee's address.\n     */\n    error CallerMustBePayee(address caller, address payee);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  signature   A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes memory signature\n    ) external;\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  r           An ECDSA/secp256k1 signature parameter.\n     * @param  vs          An ECDSA/secp256k1 short signature parameter.\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes32 r,\n        bytes32 vs\n    ) external;\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  v           v of the signature.\n     * @param  r           r of the signature.\n     * @param  s           s of the signature.\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  signature   A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes memory signature\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  r           An ECDSA/secp256k1 signature parameter.\n     * @param  vs          An ECDSA/secp256k1 short signature parameter.\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes32 r,\n        bytes32 vs\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  v           v of the signature.\n     * @param  r           r of the signature.\n     * @param  s           s of the signature.\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  signature  A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  r          An ECDSA/secp256k1 signature parameter.\n     * @param  vs         An ECDSA/secp256k1 short signature parameter.\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, bytes32 r, bytes32 vs) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  v          v of the signature.\n     * @param  r          r of the signature.\n     * @param  s          s of the signature.\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the state of an authorization.\n     * @dev    Nonces are randomly generated 32-byte data unique to the authorizer's address\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @return True if the nonce is used.\n     */\n    function authorizationState(address authorizer, bytes32 nonce) external view returns (bool);\n\n    /// @notice Returns `transferWithAuthorization` typehash.\n    function TRANSFER_WITH_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n\n    /// @notice Returns `receiveWithAuthorization` typehash.\n    function RECEIVE_WITH_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n\n    /// @notice Returns `cancelAuthorization` typehash.\n    function CANCEL_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n}\n"
      },
      "lib/ttg/lib/common/src/interfaces/IStatefulERC712.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC712Extended } from \"./IERC712Extended.sol\";\n\n/**\n * @title  Stateful Extension for EIP-712 typed structured data hashing and signing with nonces.\n * @author M^0 Labs\n */\ninterface IStatefulERC712 is IERC712Extended {\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when a signing account's nonce is not the expected current nonce.\n     * @param  nonce         The nonce used in the signature.\n     * @param  expectedNonce The expected nonce to be used in a signature by the signing account.\n     */\n    error InvalidAccountNonce(uint256 nonce, uint256 expectedNonce);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the next nonce to be used in a signature by `account`.\n     * @param  account The address of some account.\n     * @return nonce   The next nonce to be used in a signature by `account`.\n     */\n    function nonces(address account) external view returns (uint256 nonce);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "common/=lib/protocol/lib/common/src/",
        "contract-test-utils/=lib/ttg/lib/erc20-helper/lib/contract-test-utils/contracts/",
        "ds-test/=lib/protocol/lib/solmate/lib/ds-test/src/",
        "erc20-helper/=lib/ttg/lib/erc20-helper/src/",
        "forge-std/=lib/forge-std/src/",
        "protocol/=lib/protocol/",
        "solmate/=lib/protocol/lib/solmate/src/",
        "ttg/=lib/ttg/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 999999
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "shanghai",
      "viaIR": false,
      "libraries": {}
    }
  }}