{"file_path":"lib/ttg/src/EmergencyGovernor.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { ThresholdGovernor } from \"./abstract/ThresholdGovernor.sol\";\n\nimport { IEmergencyGovernor } from \"./interfaces/IEmergencyGovernor.sol\";\nimport { IRegistrar } from \"./interfaces/IRegistrar.sol\";\nimport { IStandardGovernor } from \"./interfaces/IStandardGovernor.sol\";\n\n/**\n * @title  An instance of a ThresholdGovernor with a unique and limited set of possible proposals.\n * @author M^0 Labs\n */\ncontract EmergencyGovernor is IEmergencyGovernor, ThresholdGovernor {\n    /* ============ Variables ============ */\n\n    /// @inheritdoc IEmergencyGovernor\n    address public immutable registrar;\n\n    /// @inheritdoc IEmergencyGovernor\n    address public immutable standardGovernor;\n\n    /// @inheritdoc IEmergencyGovernor\n    address public immutable zeroGovernor;\n\n    /* ============ Modifiers ============ */\n\n    /// @dev Throws if called by any account other than the Zero Governor.\n    modifier onlyZeroGovernor() {\n        if (msg.sender != zeroGovernor) revert NotZeroGovernor();\n        _;\n    }\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Constructs a new Emergency Governor contract.\n     * @param  voteToken_        The address of the Vote Token contract.\n     * @param  zeroGovernor_     The address of the Zero Governor contract.\n     * @param  registrar_        The address of the Registrar contract.\n     * @param  standardGovernor_ The address of the StandardGovernor contract.\n     * @param  thresholdRatio_   The initial threshold ratio.\n     */\n    constructor(\n        address voteToken_,\n        address zeroGovernor_,\n        address registrar_,\n        address standardGovernor_,\n        uint16 thresholdRatio_\n    ) ThresholdGovernor(\"EmergencyGovernor\", voteToken_, thresholdRatio_) {\n        if ((zeroGovernor = zeroGovernor_) == address(0)) revert InvalidZeroGovernorAddress();\n        if ((registrar = registrar_) == address(0)) revert InvalidRegistrarAddress();\n        if ((standardGovernor = standardGovernor_) == address(0)) revert InvalidStandardGovernorAddress();\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IEmergencyGovernor\n    function setThresholdRatio(uint16 newThresholdRatio_) external onlyZeroGovernor {\n        _setThresholdRatio(newThresholdRatio_);\n    }\n\n    /* ============ Proposal Functions ============ */\n\n    /// @inheritdoc IEmergencyGovernor\n    function addToList(bytes32 list_, address account_) external onlySelf {\n        _addToList(list_, account_);\n    }\n\n    /// @inheritdoc IEmergencyGovernor\n    function removeFromList(bytes32 list_, address account_) external onlySelf {\n        _removeFromList(list_, account_);\n    }\n\n    /// @inheritdoc IEmergencyGovernor\n    function removeFromAndAddToList(bytes32 list_, address accountToRemove_, address accountToAdd_) external onlySelf {\n        _removeFromList(list_, accountToRemove_);\n        _addToList(list_, accountToAdd_);\n    }\n\n    /// @inheritdoc IEmergencyGovernor\n    function setKey(bytes32 key_, bytes32 value_) external onlySelf {\n        IRegistrar(registrar).setKey(key_, value_);\n    }\n\n    /// @inheritdoc IEmergencyGovernor\n    function setStandardProposalFee(uint256 newProposalFee_) external onlySelf {\n        IStandardGovernor(standardGovernor).setProposalFee(newProposalFee_);\n    }\n\n    /* ============ Internal Interactive Functions ============ */\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   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    /* ============ Internal View/Pure Functions ============ */\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.setStandardProposalFee.selector && length == _SELECTOR_PLUS_1_ARGS)\n        ) revert InvalidCallData();\n    }\n}\n","deployed_bytecode":"0x608060405260043610610371575f3560e01c8063849a83b4116101c8578063c01f9e37116100fd578063d11d19c21161009d578063eb9019d41161006d578063eb9019d414610b1c578063f046c64614610b3b578063fb999fcb14610b6e578063fc0c546a14610b8d575f80fd5b8063d11d19c214610a83578063d48d842314610ab6578063dd4e2ba514610ad5578063deaaa7cc14610ae9575f80fd5b8063c59057e4116100d8578063c59057e4146109f3578063c64d2ee614610a12578063c7f758a814610a31578063cee8770814610a64575f80fd5b8063c01f9e3714610992578063c0324da1146109b1578063c2ee3a08146109de575f80fd5b806396ccd67311610168578063a7713a7011610143578063a7713a701461092a578063b4d87a1214610942578063b577512514610961578063b58131b014610980575f80fd5b806396ccd673146108d857806397c3d334146108f75780639b9e9cf81461090b575f80fd5b80638df3227f116101a35780638df3227f146108285780638e9d8c341461085b57806391ddadf41461088e57806394eac995146108b9575f80fd5b8063849a83b4146107c357806384b0196e146107e25780638968eb0714610809575f80fd5b80633bccf4fd116102a9578063544ffc9c1161024957806364a38bf91161021957806364a38bf91461074757806370edcbc4146107665780637b3c71d3146107855780637d5e81e2146107a4575f80fd5b8063544ffc9c1461069557806355a73c53146106ea57806356781388146107095780635b18c26a14610728575f80fd5b80634bf5d7e9116102845780634bf5d7e9146106105780634d6d7441146106245780634d8e082514610657578063519c958714610676575f80fd5b80633bccf4fd1461057c5780633e4f49e61461059b57806343859632146105c7575f80fd5b806324b2c7b3116103145780632d63f693116102ef5780632d63f6931461051657806330717129146105355780633644e515146105545780633932abb114610568575f80fd5b806324b2c7b3146104b15780632656227d146104d05780632b20e397146104e3575f80fd5b80630dd320e91161034f5780630dd320e9146103de578063143489d0146103fd578063160d66ae1461046a5780631703a0181461049d575f80fd5b806302a251a31461037557806306fdde031461039c57806307a00330146103bd575b5f80fd5b348015610380575f80fd5b50610389610bbf565b6040519081526020015b60405180910390f35b3480156103a7575f80fd5b506103b0610bcc565b60405161039391906131be565b3480156103c8575f80fd5b506103dc6103d73660046131d0565b610c5b565b005b3480156103e9575f80fd5b506103896103f836600461335f565b610d0a565b348015610408575f80fd5b506104456104173660046133fb565b5f908152600160205260409020546301000000900473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610393565b348015610475575f80fd5b506104457f0000000000000000000000005983b89fa184f14917013b9c3062afd9434c5b0381565b3480156104a8575f80fd5b50610389610dd4565b3480156104bc575f80fd5b506103896104cb366004613412565b610df1565b6103896104de366004613612565b610e09565b3480156104ee575f80fd5b506104457f000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c81565b348015610521575f80fd5b506103896105303660046133fb565b610e5a565b348015610540575f80fd5b5061038961054f36600461369c565b610e82565b34801561055f575f80fd5b50610389610f0a565b348015610573575f80fd5b50610389610f5f565b348015610587575f80fd5b50610389610596366004613771565b610f66565b3480156105a6575f80fd5b506105ba6105b53660046133fb565b610f95565b6040516103939190613821565b3480156105d2575f80fd5b506106006105e136600461382f565b600260209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610393565b34801561061b575f80fd5b506103b06110f9565b34801561062f575f80fd5b506104457f000000000000000000000000b024ac5a7c6bc92fbacc8c3387e628a07e1da01681565b348015610662575f80fd5b50610389610671366004613859565b611103565b348015610681575f80fd5b506103dc61069036600461388b565b611113565b3480156106a0575f80fd5b506106cf6106af3660046133fb565b5f8181526001602081905260408220908101546002909101549093909250565b60408051938452602084019290925290820152606001610393565b3480156106f5575f80fd5b506103896107043660046138c4565b611134565b348015610714575f80fd5b506103896107233660046138c4565b611146565b348015610733575f80fd5b506103896107423660046138e5565b611161565b348015610752575f80fd5b50610389610761366004613949565b611193565b348015610771575f80fd5b50610389610780366004613949565b6111b5565b348015610790575f80fd5b5061038961079f3660046139ee565b6111f5565b3480156107af575f80fd5b506103896107be366004613a38565b611237565b3480156107ce575f80fd5b506103896107dd366004613412565b61124e565b3480156107ed575f80fd5b506107f66112ae565b6040516103939796959493929190613b0c565b348015610814575f80fd5b50610389610823366004613b94565b6113e6565b348015610833575f80fd5b506104457f000000000000000000000000a0dafaeea4a1d44534e1b9227e19cae6358b80fe81565b348015610866575f80fd5b506103897fa891f76027ef63a24501b9dd3b0c779b49ad26d2328e9d423640209d1ad4fcc481565b348015610899575f80fd5b506108a2611455565b60405165ffffffffffff9091168152602001610393565b3480156108c4575f80fd5b506103dc6108d3366004613c21565b61145e565b3480156108e3575f80fd5b506103896108f23660046139ee565b6114d9565b348015610902575f80fd5b50612710610389565b348015610916575f80fd5b50610389610925366004613c42565b6114e6565b348015610935575f80fd5b5060035461ffff16610389565b34801561094d575f80fd5b506103dc61095c36600461382f565b611568565b34801561096c575f80fd5b506103dc61097b3660046133fb565b61157e565b34801561098b575f80fd5b505f610389565b34801561099d575f80fd5b506103896109ac3660046133fb565b611624565b3480156109bc575f80fd5b506003546109cb9061ffff1681565b60405161ffff9091168152602001610393565b3480156109e9575f80fd5b5061038961271081565b3480156109fe575f80fd5b50610389610a0d366004613612565b61163e565b348015610a1d575f80fd5b50610389610a2c366004613cf6565b611661565b348015610a3c575f80fd5b50610a50610a4b3660046133fb565b6116b3565b604051610393989796959493929190613d69565b348015610a6f575f80fd5b50610389610a7e366004613dd2565b61176e565b348015610a8e575f80fd5b506103897f7949bd92105c02f48ca245aa185f4a7a4d7185641d59b186ac64abeb44964f0c81565b348015610ac1575f80fd5b506103dc610ad036600461382f565b6117be565b348015610ae0575f80fd5b506103b06117d0565b348015610af4575f80fd5b506103897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610b27575f80fd5b50610389610b36366004613e4e565b6117f0565b348015610b46575f80fd5b506103897f9a121fc10d6025acfc09275f9709796b68831733b5bbac0d510d13f85b1b730f81565b348015610b79575f80fd5b50610389610b883660046133fb565b6118a9565b348015610b98575f80fd5b507f0000000000000000000000005983b89fa184f14917013b9c3062afd9434c5b03610445565b5f60015b61ffff16905090565b60605f8054610bda90613e76565b80601f0160208091040260200160405190810160405280929190818152602001828054610c0690613e76565b8015610c515780601f10610c2857610100808354040283529160200191610c51565b820191905f5260205f20905b815481529060010190602001808311610c3457829003601f168201915b5050505050905090565b610c636118e4565b6040517f07a0033000000000000000000000000000000000000000000000000000000000815260048101839052602481018290527f000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c73ffffffffffffffffffffffffffffffffffffffff16906307a00330906044015b5f604051808303815f87803b158015610cf0575f80fd5b505af1158015610d02573d5f803e3d5ffd5b505050505050565b5f610d6f87610d698888604051602001610d25929190613ec7565b604051602081830303815290604052805190602001208787604051602001610d4e929190613f07565b6040516020818303038152906040528051906020012061191f565b8461197b565b610dc987878787878267ffffffffffffffff811115610d9057610d90613259565b604051908082528060200260200182016040528015610dc357816020015b6060815260200190600190039081610dae5790505b506119cc565b979650505050505050565b5f610dec610de0611b19565b60035461ffff16611b22565b905090565b5f610dc93388888888610e04888a613f40565b6119cc565b5f610e15858585611b4c565b5f610e1e611b19565b9050610e50845f81518110610e3557610e35613fb0565b602002602001015182600184610e4b919061400a565b611cef565b9695505050505050565b5f818152600160208190526040822054610e78919061ffff1661400a565b61ffff1692915050565b5f610eeb89610d698a8a604051602001610e9d929190613ec7565b604051602081830303815290604052805190602001208989604051602001610ec6929190613f07565b60405160208183030381529060405280519060200120610ee68989611de3565b611ec6565b610efd8989898989610e04898b613f40565b9998505050505050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000014614610f3a57610dec611f1a565b507f03b719ed21fa015c2dd9fe6b6a0f4a6c21df6120463e1389618fccfe8d08dd0490565b5f80610bc3565b5f610e50610f7f610f778888611fb4565b868686611ffb565b878760405180602001604052805f81525061201f565b5f818152600160205260408120805462010000900460ff1615610fbb5750600792915050565b805461ffff165f819003610ffb576040517fd9c78e0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61100f61100a60018461400a565b6120ca565b90505f6001830161ffff16611022611b19565b61ffff1611159050815f03611049578061103d576006610e50565b60019695505050505050565b835477010000000000000000000000000000000000000000000000900461ffff16611074838261402c565b6127108660020154611086919061402c565b106110a45781611097576006610dc9565b6004979650505050505050565b6110b28361ffff831661402c565b6127108660010154856110c59190614043565b6110cf919061402c565b101580156110da5750815b156110ec575060019695505050505050565b5060039695505050505050565b6060610dec61217c565b5f61110d8261219c565b92915050565b61111b6118e4565b61112583836121ae565b61112f8382612229565b505050565b5f61113f8383611fb4565b9392505050565b5f61113f33848460405180602001604052805f81525061201f565b5f61117085610d698686611fb4565b61118a85858560405180602001604052805f81525061201f565b95945050505050565b5f61118a33868686868267ffffffffffffffff811115610d9057610d90613259565b5f61118a85856040516020016111cc929190613ec7565b604051602081830303815290604052805190602001208484604051602001610d4e929190613f07565b5f61118a33868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061201f92505050565b5f611244858585856122a4565b5095945050505050565b5f610dc98787604051602001611265929190613ec7565b60405160208183030381529060405280519060200120868660405160200161128e929190613f07565b60405160208183030381529060405280519060200120610ee68686611de3565b5f6060808280808381463082806040519080825280602002602001820160405280156112e4578160200160208202803683370190505b507f0f00000000000000000000000000000000000000000000000000000000000000949392919084805461131790613e76565b80601f016020809104026020016040519081016040528092919081815260200182805461134390613e76565b801561138e5780601f106113655761010080835404028352916020019161138e565b820191905f5260205f20905b81548152906001019060200180831161137157829003601f168201915b505050505094506040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525093929190965096509650965096509650965090919293949596565b5f61144961142c610f778a8a604051602001611403929190613ec7565b604051602081830303815290604052805190602001208989604051602001610d4e929190613f07565b898989898267ffffffffffffffff811115610d9057610d90613259565b98975050505050505050565b5f610bc3611b19565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0dafaeea4a1d44534e1b9227e19cae6358b80fe16146114cd576040517fb30b9d4300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114d6816124f3565b50565b5f61118a85858585612602565b5f61155a61154c610f778c8c604051602001611503929190613ec7565b604051602081830303815290604052805190602001208b8b60405160200161152c929190613f07565b60405160208183030381529060405280519060200120610ee68b8b611de3565b8b8b8b8b610e048b8d613f40565b9a9950505050505050505050565b6115706118e4565b61157a8282612229565b5050565b6115866118e4565b6040517f10bf5068000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000b024ac5a7c6bc92fbacc8c3387e628a07e1da01673ffffffffffffffffffffffffffffffffffffffff16906310bf5068906024015f604051808303815f87803b15801561160b575f80fd5b505af115801561161d573d5f803e3d5ffd5b5050505050565b5f81815260016020819052604082205461ffff1601610e78565b5f61118a835f8151811061165457611654613fb0565b602002602001015161219c565b5f61167287610d6988888888612602565b610dc987878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061201f92505050565b5f818152600160205260408120805461ffff1691908190819081908190819081906116de8960010190565b61ffff1697506116ed8a610f95565b600182015460028301548354929950909750955073ffffffffffffffffffffffffffffffffffffffff6301000000820416945061174c9061ffff8082169177010000000000000000000000000000000000000000000000900416611b22565b9250805f0160179054906101000a900461ffff16915050919395975091939597565b5f611449611781610f778a8a8a8a612602565b898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061201f92505050565b6117c66118e4565b61157a82826121ae565b60606040518060600160405280602d81526020016144ee602d9139905090565b6040517f3a46b1a800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390525f917f0000000000000000000000005983b89fa184f14917013b9c3062afd9434c5b0390911690633a46b1a890604401602060405180830381865afa158015611885573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061113f9190614056565b5f818152600160205260408120805461113f9061ffff8082169177010000000000000000000000000000000000000000000000900416611b22565b33301461191d576040517f29c3b7ee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b604080517f9a121fc10d6025acfc09275f9709796b68831733b5bbac0d510d13f85b1b730f6020820152908101839052606081018290525f9061113f906080015b6040516020818303038152906040528051906020012061266c565b5f6119878484846126cd565b90505f81600581111561199c5761199c6137bb565b036119a75750505050565b6119b2848484612707565b156119bd5750505050565b6119c68161284f565b50505050565b5f84808203611a07576040517f75672da700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808414611a4f576040517ffa5dbe0800000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044015b60405180910390fd5b82518114611a965782516040517ffa5dbe08000000000000000000000000000000000000000000000000000000008152611a46918391600401918252602082015260400190565b5f5b81811015611b0d57611b0389898984818110611ab657611ab6613fb0565b90506020020135888885818110611acf57611acf613fb0565b9050602002016020810190611ae4919061406d565b878581518110611af657611af6613fb0565b602002602001015161201f565b9250600101611a98565b50509695505050505050565b5f610dec612a13565b5f612710611b3461100a60018661400a565b611b429061ffff851661402c565b61113f9190614086565b8251600114611b87576040517f83913ab500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16835f81518110611bb057611bb0613fb0565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614611c05576040517f82d5d76a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151600114611c40576040517f32143ab000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81518110611c5257611c52613fb0565b60200260200101515f14611c92576040517faa7feadc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600114611ccd576040517fc569313f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61112f815f81518110611ce257611ce2613fb0565b6020026020010151612a3b565b5f3415611d28576040517faa7feadc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8161ffff165f03611d65576040517f0797d96900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8161ffff168361ffff1610611db1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830192611da3908590612c3b565b9050805f0361113f57611d65565b6040517fb696436000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81818167ffffffffffffffff811115611dff57611dff613259565b604051908082528060200260200182016040528015611e28578160200160208202803683370190505b5090505f5b82811015611e9457858582818110611e4757611e47613fb0565b9050602002810190611e5991906140be565b604051611e6792919061411f565b6040518091039020828281518110611e8157611e81613fb0565b6020908102919091010152600101611e2d565b5080604051602001611ea6919061412e565b604051602081830303815290604052805190602001209250505092915050565b604080517fa891f76027ef63a24501b9dd3b0c779b49ad26d2328e9d423640209d1ad4fcc4602082015290810184905260608101839052608081018290525f90611f129060a001611960565b949350505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f5f1b5f604051611f4c9190614163565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810183905260ff821660608201525f9061113f90608001611960565b5f8061200986868686612daa565b925090506120168161284f565b50949350505050565b5f8061202a85610f95565b90506001816007811115612040576120406137bb565b1461207957806040517f88f40ea0000000000000000000000000000000000000000000000000000000008152600401611a469190613821565b5f858152600160205260409020546120bb9087907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61ffff91821601166117f0565b91506120168683878787612eb7565b6040517f5c7e5d5f00000000000000000000000000000000000000000000000000000000815261ffff821660048201525f907f0000000000000000000000005983b89fa184f14917013b9c3062afd9434c5b0373ffffffffffffffffffffffffffffffffffffffff1690635c7e5d5f90602401602060405180830381865afa158015612158573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110d9190614056565b60606040518060a001604052806065815260200161448960659139905090565b5f61110d826121a9613069565b613079565b6040517fd48d84230000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff82811660248301527f000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c169063d48d842390604401610cd9565b6040517fb4d87a120000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff82811660248301527f000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c169063b4d87a1290604401610cd9565b5f806122b1868686611b4c565b6122b9613069565b90506122de845f815181106122d0576122d0613fb0565b602002602001015182613079565b5f8181526001602052604090205490925061ffff161561232a576040517f5c36267800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61245382826040805160c08101825261ffff92831681525f6020808301828152338486019081526003548716606086019081526080860185815260a087018681529986526001948590529690942094518554925191519451881677010000000000000000000000000000000000000000000000027fffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff96909616630100000002959095167fffffffffffffff00000000000000000000000000000000000000000000ffffff92151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000090941691909816179190911716949094171781559051918101919091559051600290910155565b7f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e0823388888a5167ffffffffffffffff81111561249257612492613259565b6040519080825280602002602001820160405280156124c557816020015b60608152602001906001900390816124b05790505b508987600181018b6040516124e2999897969594939291906142ae565b60405180910390a194509492505050565b6127108161ffff16118061250c575061010f61ffff8216105b15612559576040517f39aa1e1800000000000000000000000000000000000000000000000000000000815261ffff8216600482015261010f60248201526127106044820152606401611a46565b6003546040805161ffff928316815291831660208301527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a1600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661ffff83169081179091556040519081527fcae6f683fe1ab8ec2737e8d7cc5b306931ad2c39aa1701b65b3e4d9492bffa649060200160405180910390a150565b5f61118a7f7949bd92105c02f48ca245aa185f4a7a4d7185641d59b186ac64abeb44964f0c5f1b8686868660405161263b92919061411f565b60405190819003812061196094939291602001938452602084019290925260ff166040830152606082015260800190565b5f612675610f0a565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b5f805f6126da85856130cc565b90925090505f8260058111156126f2576126f26137bb565b146126fd5781610e50565b610e508682613110565b5f805f8573ffffffffffffffffffffffffffffffffffffffff16858560405160240161273492919061438a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1626ba7e00000000000000000000000000000000000000000000000000000000179052516127b591906143a2565b5f60405180830381855afa9150503d805f81146127ed576040519150601f19603f3d011682016040523d82523d5f602084013e6127f2565b606091505b509150915081801561280657506020815110155b8015610e50575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906128449083016020908101908401614056565b149695505050505050565b5f816005811115612862576128626137bb565b0361286a5750565b600181600581111561287e5761287e6137bb565b036128b5576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028160058111156128c9576128c96137bb565b03612900576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003816005811115612914576129146137bb565b0361294b576040517fbf4bf5b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600481600581111561295f5761295f6137bb565b03612996576040517fff551e8900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058160058111156129aa576129aa6137bb565b036129e1576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6213c680612a2663661bd35042614043565b612a309190614086565b610dec9060016143bd565b5f612a45826143d0565b82519091507fffffffff0000000000000000000000000000000000000000000000000000000082167fb4d87a1200000000000000000000000000000000000000000000000000000000148015612a9b5750604481145b158015612af657507fffffffff0000000000000000000000000000000000000000000000000000000082167fd48d842300000000000000000000000000000000000000000000000000000000148015612af45750604481145b155b8015612b5057507fffffffff0000000000000000000000000000000000000000000000000000000082167f519c958700000000000000000000000000000000000000000000000000000000148015612b4e5750606481145b155b8015612baa57507fffffffff0000000000000000000000000000000000000000000000000000000082167f07a0033000000000000000000000000000000000000000000000000000000000148015612ba85750604481145b155b8015612c0457507fffffffff0000000000000000000000000000000000000000000000000000000082167fb577512500000000000000000000000000000000000000000000000000000000148015612c025750602481145b155b1561112f576040517f1c49f4d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612c468383613079565b5f81815260016020526040902080549192509061ffff848116911614612c6f575f91505061110d565b6004612c7a83610f95565b6007811115612c8b57612c8b6137bb565b14612c99575f91505061110d565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff16620100001781556040517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90612cf69084815260200190565b60405180910390a15f803073ffffffffffffffffffffffffffffffffffffffff1686604051612d2591906143a2565b5f604051808303815f865af19150503d805f8114612d5e576040519150601f19603f3d011682016040523d82523d5f602084013e612d63565b606091505b509150915081612da157806040517f15fcd675000000000000000000000000000000000000000000000000000000008152600401611a4691906131be565b50505092915050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612ddf5750600390505f612eae565b8460ff16601b14158015612df757508460ff16601c14155b15612e075750600490505f612eae565b604080515f81526020810180835288905260ff871691810191909152606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612e57573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615612ea5575f81612ea9565b60015f5b915091505b94509492505050565b835f03612ef0576040517f8791239e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845290915290205460ff1615612f59576040517f7c9a1cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558260ff166001811115612fc557612fc56137bb565b6001811115612fd657612fd66137bb565b03612ff7575f8381526001602081905260409091200180548501905561300e565b5f8381526001602052604090206002018054850190555b8473ffffffffffffffffffffffffffffffffffffffff167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48484878560405161305a949392919061441f565b60405180910390a25050505050565b5f80613073611b19565b01905090565b5f82823060405160200161308f93929190614446565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209392505050565b5f8082516041146130e25750600290505f613109565b6020830151604084015160608501515f1a919061310187848484612daa565b945094505050505b9250929050565b5f8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461314b57600561113f565b505f92915050565b5f5b8381101561316d578181015183820152602001613155565b50505f910152565b5f815180845261318c816020860160208601613153565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61113f6020830184613175565b5f80604083850312156131e1575f80fd5b50508035926020909101359150565b803573ffffffffffffffffffffffffffffffffffffffff81168114613213575f80fd5b919050565b5f8083601f840112613228575f80fd5b50813567ffffffffffffffff81111561323f575f80fd5b6020830191508360208260051b8501011115613109575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156132cd576132cd613259565b604052919050565b5f82601f8301126132e4575f80fd5b813567ffffffffffffffff8111156132fe576132fe613259565b61332f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613286565b818152846020838601011115613343575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060808789031215613374575f80fd5b61337d876131f0565b9550602087013567ffffffffffffffff80821115613399575f80fd5b6133a58a838b01613218565b909750955060408901359150808211156133bd575f80fd5b6133c98a838b01613218565b909550935060608901359150808211156133e1575f80fd5b506133ee89828a016132d5565b9150509295509295509295565b5f6020828403121561340b575f80fd5b5035919050565b5f805f805f8060608789031215613427575f80fd5b863567ffffffffffffffff8082111561343e575f80fd5b61344a8a838b01613218565b90985096506020890135915080821115613462575f80fd5b61346e8a838b01613218565b90965094506040890135915080821115613486575f80fd5b5061349389828a01613218565b979a9699509497509295939492505050565b5f67ffffffffffffffff8211156134be576134be613259565b5060051b60200190565b5f82601f8301126134d7575f80fd5b813560206134ec6134e7836134a5565b613286565b8083825260208201915060208460051b87010193508684111561350d575f80fd5b602086015b8481101561353057613523816131f0565b8352918301918301613512565b509695505050505050565b5f82601f83011261354a575f80fd5b8135602061355a6134e7836134a5565b8083825260208201915060208460051b87010193508684111561357b575f80fd5b602086015b848110156135305780358352918301918301613580565b5f82601f8301126135a6575f80fd5b813560206135b66134e7836134a5565b82815260059290921b840181019181810190868411156135d4575f80fd5b8286015b8481101561353057803567ffffffffffffffff8111156135f6575f80fd5b6136048986838b01016132d5565b8452509183019183016135d8565b5f805f8060808587031215613625575f80fd5b843567ffffffffffffffff8082111561363c575f80fd5b613648888389016134c8565b9550602087013591508082111561365d575f80fd5b6136698883890161353b565b9450604087013591508082111561367e575f80fd5b5061368b87828801613597565b949793965093946060013593505050565b5f805f805f805f8060a0898b0312156136b3575f80fd5b6136bc896131f0565b9750602089013567ffffffffffffffff808211156136d8575f80fd5b6136e48c838d01613218565b909950975060408b01359150808211156136fc575f80fd5b6137088c838d01613218565b909750955060608b0135915080821115613720575f80fd5b61372c8c838d01613218565b909550935060808b0135915080821115613744575f80fd5b506137518b828c016132d5565b9150509295985092959890939650565b803560ff81168114613213575f80fd5b5f805f805f60a08688031215613785575f80fd5b8535945061379560208701613761565b93506137a360408701613761565b94979396509394606081013594506080013592915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6008811061381d577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b6020810161110d82846137e8565b5f8060408385031215613840575f80fd5b82359150613850602084016131f0565b90509250929050565b5f60208284031215613869575f80fd5b813567ffffffffffffffff81111561387f575f80fd5b611f12848285016132d5565b5f805f6060848603121561389d575f80fd5b833592506138ad602085016131f0565b91506138bb604085016131f0565b90509250925092565b5f80604083850312156138d5575f80fd5b8235915061385060208401613761565b5f805f80608085870312156138f8575f80fd5b613901856131f0565b93506020850135925061391660408601613761565b9150606085013567ffffffffffffffff811115613931575f80fd5b61393d878288016132d5565b91505092959194509250565b5f805f806040858703121561395c575f80fd5b843567ffffffffffffffff80821115613973575f80fd5b61397f88838901613218565b90965094506020870135915080821115613997575f80fd5b506139a487828801613218565b95989497509550505050565b5f8083601f8401126139c0575f80fd5b50813567ffffffffffffffff8111156139d7575f80fd5b602083019150836020828501011115613109575f80fd5b5f805f8060608587031215613a01575f80fd5b84359350613a1160208601613761565b9250604085013567ffffffffffffffff811115613a2c575f80fd5b6139a4878288016139b0565b5f805f8060808587031215613a4b575f80fd5b843567ffffffffffffffff80821115613a62575f80fd5b613a6e888389016134c8565b95506020870135915080821115613a83575f80fd5b613a8f8883890161353b565b94506040870135915080821115613aa4575f80fd5b613ab088838901613597565b93506060870135915080821115613ac5575f80fd5b5061393d878288016132d5565b5f815180845260208085019450602084015f5b83811015613b0157815187529582019590820190600101613ae5565b509495945050505050565b7fff000000000000000000000000000000000000000000000000000000000000008816815260e060208201525f613b4660e0830189613175565b8281036040840152613b588189613175565b905086606084015273ffffffffffffffffffffffffffffffffffffffff861660808401528460a084015282810360c084015261155a8185613ad2565b5f805f805f805f60a0888a031215613baa575f80fd5b873567ffffffffffffffff80821115613bc1575f80fd5b613bcd8b838c01613218565b909950975060208a0135915080821115613be5575f80fd5b50613bf28a828b01613218565b9096509450613c05905060408901613761565b9250606088013591506080880135905092959891949750929550565b5f60208284031215613c31575f80fd5b813561ffff8116811461113f575f80fd5b5f805f805f805f805f60c08a8c031215613c5a575f80fd5b893567ffffffffffffffff80821115613c71575f80fd5b613c7d8d838e01613218565b909b50995060208c0135915080821115613c95575f80fd5b613ca18d838e01613218565b909950975060408c0135915080821115613cb9575f80fd5b50613cc68c828d01613218565b9096509450613cd9905060608b01613761565b925060808a0135915060a08a013590509295985092959850929598565b5f805f805f8060a08789031215613d0b575f80fd5b613d14876131f0565b955060208701359450613d2960408801613761565b9350606087013567ffffffffffffffff80821115613d45575f80fd5b613d518a838b016139b0565b909550935060808901359150808211156133e1575f80fd5b65ffffffffffff8981168252881660208201526101008101613d8e60408301896137e8565b6060820196909652608081019490945273ffffffffffffffffffffffffffffffffffffffff9290921660a084015260c083015261ffff1660e0909101529392505050565b5f805f805f805f60c0888a031215613de8575f80fd5b87359650613df860208901613761565b9550604088013567ffffffffffffffff811115613e13575f80fd5b613e1f8a828b016139b0565b9096509450613e32905060608901613761565b92506080880135915060a0880135905092959891949750929550565b5f8060408385031215613e5f575f80fd5b613e68836131f0565b946020939093013593505050565b600181811c90821680613e8a57607f821691505b602082108103613ec1577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613ef4575f80fd5b8260051b80858437919091019392505050565b5f8184825b85811015613f355760ff613f1f83613761565b1683526020928301929190910190600101613f0c565b509095945050505050565b5f613f4d6134e7846134a5565b80848252602080830192508560051b850136811115613f6a575f80fd5b855b81811015613fa457803567ffffffffffffffff811115613f8a575f80fd5b613f9636828a016132d5565b865250938201938201613f6c565b50919695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b61ffff82811682821603908082111561402557614025613fdd565b5092915050565b808202811582820484141761110d5761110d613fdd565b8181038181111561110d5761110d613fdd565b5f60208284031215614066575f80fd5b5051919050565b5f6020828403121561407d575f80fd5b61113f82613761565b5f826140b9577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126140f1575f80fd5b83018035915067ffffffffffffffff82111561410b575f80fd5b602001915036819003821315613109575f80fd5b818382375f9101908152919050565b81515f9082906020808601845b838110156141575781518552938201939082019060010161413b565b50929695505050505050565b5f8083545f60018260011c9150600183168061418057607f831692505b602080841082036141b8577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b8180156141cc57600181146141ff5761422a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616895284151585028901965061422a565b5f8a8152602090205f5b868110156142225781548b820152908501908301614209565b505084890196505b509498975050505050505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156142a1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895261428f838351613175565b98840198925090830190600101614255565b5090979650505050505050565b5f6101208083018c8452602073ffffffffffffffffffffffffffffffffffffffff808e1660208701528360408701528293508c518084526101408701945060208e0193505f5b818110156143125784518316865294830194938301936001016142f4565b50505050508281036060840152614329818a613ad2565b9050828103608084015261433d8189614238565b905082810360a08401526143518188614238565b61ffff871660c0850152905061ffff851660e084015282810361010084015261437a8185613175565b9c9b505050505050505050505050565b828152604060208201525f611f126040830184613175565b5f82516143b3818460208701613153565b9190910192915050565b8082018082111561110d5761110d613fdd565b5f815160208301517fffffffff00000000000000000000000000000000000000000000000000000000808216935060048310156144175780818460040360031b1b83161693505b505050919050565b84815260ff84166020820152826040820152608060608201525f610e506080830184613175565b606081525f6144586060830186613175565b905061ffff8416602083015273ffffffffffffffffffffffffffffffffffffffff8316604083015294935050505056fe6d6f64653d65706f63682665706f6368556e6465726c79696e67536f757263653d626c6f636b54696d657374616d702665706f63685374617274696e6754696d657374616d703d313731333039393630302665706f6368506572696f643d31323936303030737570706f72743d616761696e73742c666f722671756f72756d3d666f7226737563636573733d71756f72756da26469706673582212206e4e4f61da996630edc3dbc3da375d7883f0096457851e1f33c6f873dd626fa564736f6c63430008170033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"shanghai","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":999999},"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/"]},"optimization_runs":999999,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0x886d405949F709bC3f4451491bDd07ff51Cdf90A/","decoded_constructor_args":[["0x5983B89FA184f14917013B9C3062afD9434C5b03",{"internalType":"address","name":"voteToken_","type":"address"}],["0xa0DAFaEEA4A1d44534e1b9227e19CAE6358b80FE",{"internalType":"address","name":"zeroGovernor_","type":"address"}],["0x119FbeeDD4F4f4298Fb59B720d5654442b81ae2c",{"internalType":"address","name":"registrar_","type":"address"}],["0xB024aC5a7c6bC92fbACc8C3387E628a07e1Da016",{"internalType":"address","name":"standardGovernor_","type":"address"}],["6500",{"internalType":"uint16","name":"thresholdRatio_","type":"uint16"}]],"compiler_version":"0.8.23+commit.f704f362","is_verified_via_verifier_alliance":false,"verified_at":"2024-05-14T13:14:17.950563Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x61014060405234801562000011575f80fd5b5060405162004b1338038062004b138339810160408190526200003491620002ea565b60408051808201909152601181527022b6b2b933b2b731bca3b7bb32b93737b960791b602082015285828282815f6200006e8282620003fd565b50466080526200007d62000153565b60a052506001600160a01b03811660c0819052620000ae576040516316d3e4a360e01b815260040160405180910390fd5b50620000bc905081620001ef565b5050506001600160a01b038416610120819052620000ed5760405163dfac64ef60e01b815260040160405180910390fd5b6001600160a01b03831660e08190526200011a5760405163a8a93d6960e01b815260040160405180910390fd5b6001600160a01b0382166101008190526200014857604051637301473d60e11b815260040160405180910390fd5b505050505062000543565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f5f1b5f604051620001879190620004c9565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6127108161ffff16118062000209575061010f61ffff8216105b15620002425760405163073543c360e31b815261ffff8216600482015261010f6024820152612710604482015260640160405180910390fd5b6003546040805161ffff928316815291831660208301527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a16003805461ffff191661ffff83169081179091556040519081527fcae6f683fe1ab8ec2737e8d7cc5b306931ad2c39aa1701b65b3e4d9492bffa649060200160405180910390a150565b80516001600160a01b0381168114620002e5575f80fd5b919050565b5f805f805f60a08688031215620002ff575f80fd5b6200030a86620002ce565b94506200031a60208701620002ce565b93506200032a60408701620002ce565b92506200033a60608701620002ce565b9150608086015161ffff8116811462000351575f80fd5b809150509295509295909350565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200038857607f821691505b602082108103620003a757634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115620003f857805f5260205f20601f840160051c81016020851015620003d45750805b601f840160051c820191505b81811015620003f5575f8155600101620003e0565b50505b505050565b81516001600160401b038111156200041957620004196200035f565b62000431816200042a845462000373565b84620003ad565b602080601f83116001811462000467575f84156200044f5750858301515b5f19600386901b1c1916600185901b178555620004c1565b5f85815260208120601f198616915b82811015620004975788860151825594840194600190910190840162000476565b5085821015620004b557878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f808354620004d88162000373565b60018281168015620004f35760018114620005095762000537565b60ff198416875282151583028701945062000537565b875f526020805f205f5b858110156200052e5781548a82015290840190820162000513565b50505082870194505b50929695505050505050565b60805160a05160c05160e0516101005161012051614550620005c35f395f8181610839015261147601525f818161063501526115b501525f81816104f401528181610c99015281816121fa015261227501525f818161047b01528181610b9b0152818161183e01526120fe01525f610f3d01525f610f0d01526145505ff3fe608060405260043610610371575f3560e01c8063849a83b4116101c8578063c01f9e37116100fd578063d11d19c21161009d578063eb9019d41161006d578063eb9019d414610b1c578063f046c64614610b3b578063fb999fcb14610b6e578063fc0c546a14610b8d575f80fd5b8063d11d19c214610a83578063d48d842314610ab6578063dd4e2ba514610ad5578063deaaa7cc14610ae9575f80fd5b8063c59057e4116100d8578063c59057e4146109f3578063c64d2ee614610a12578063c7f758a814610a31578063cee8770814610a64575f80fd5b8063c01f9e3714610992578063c0324da1146109b1578063c2ee3a08146109de575f80fd5b806396ccd67311610168578063a7713a7011610143578063a7713a701461092a578063b4d87a1214610942578063b577512514610961578063b58131b014610980575f80fd5b806396ccd673146108d857806397c3d334146108f75780639b9e9cf81461090b575f80fd5b80638df3227f116101a35780638df3227f146108285780638e9d8c341461085b57806391ddadf41461088e57806394eac995146108b9575f80fd5b8063849a83b4146107c357806384b0196e146107e25780638968eb0714610809575f80fd5b80633bccf4fd116102a9578063544ffc9c1161024957806364a38bf91161021957806364a38bf91461074757806370edcbc4146107665780637b3c71d3146107855780637d5e81e2146107a4575f80fd5b8063544ffc9c1461069557806355a73c53146106ea57806356781388146107095780635b18c26a14610728575f80fd5b80634bf5d7e9116102845780634bf5d7e9146106105780634d6d7441146106245780634d8e082514610657578063519c958714610676575f80fd5b80633bccf4fd1461057c5780633e4f49e61461059b57806343859632146105c7575f80fd5b806324b2c7b3116103145780632d63f693116102ef5780632d63f6931461051657806330717129146105355780633644e515146105545780633932abb114610568575f80fd5b806324b2c7b3146104b15780632656227d146104d05780632b20e397146104e3575f80fd5b80630dd320e91161034f5780630dd320e9146103de578063143489d0146103fd578063160d66ae1461046a5780631703a0181461049d575f80fd5b806302a251a31461037557806306fdde031461039c57806307a00330146103bd575b5f80fd5b348015610380575f80fd5b50610389610bbf565b6040519081526020015b60405180910390f35b3480156103a7575f80fd5b506103b0610bcc565b60405161039391906131be565b3480156103c8575f80fd5b506103dc6103d73660046131d0565b610c5b565b005b3480156103e9575f80fd5b506103896103f836600461335f565b610d0a565b348015610408575f80fd5b506104456104173660046133fb565b5f908152600160205260409020546301000000900473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610393565b348015610475575f80fd5b506104457f000000000000000000000000000000000000000000000000000000000000000081565b3480156104a8575f80fd5b50610389610dd4565b3480156104bc575f80fd5b506103896104cb366004613412565b610df1565b6103896104de366004613612565b610e09565b3480156104ee575f80fd5b506104457f000000000000000000000000000000000000000000000000000000000000000081565b348015610521575f80fd5b506103896105303660046133fb565b610e5a565b348015610540575f80fd5b5061038961054f36600461369c565b610e82565b34801561055f575f80fd5b50610389610f0a565b348015610573575f80fd5b50610389610f5f565b348015610587575f80fd5b50610389610596366004613771565b610f66565b3480156105a6575f80fd5b506105ba6105b53660046133fb565b610f95565b6040516103939190613821565b3480156105d2575f80fd5b506106006105e136600461382f565b600260209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610393565b34801561061b575f80fd5b506103b06110f9565b34801561062f575f80fd5b506104457f000000000000000000000000000000000000000000000000000000000000000081565b348015610662575f80fd5b50610389610671366004613859565b611103565b348015610681575f80fd5b506103dc61069036600461388b565b611113565b3480156106a0575f80fd5b506106cf6106af3660046133fb565b5f8181526001602081905260408220908101546002909101549093909250565b60408051938452602084019290925290820152606001610393565b3480156106f5575f80fd5b506103896107043660046138c4565b611134565b348015610714575f80fd5b506103896107233660046138c4565b611146565b348015610733575f80fd5b506103896107423660046138e5565b611161565b348015610752575f80fd5b50610389610761366004613949565b611193565b348015610771575f80fd5b50610389610780366004613949565b6111b5565b348015610790575f80fd5b5061038961079f3660046139ee565b6111f5565b3480156107af575f80fd5b506103896107be366004613a38565b611237565b3480156107ce575f80fd5b506103896107dd366004613412565b61124e565b3480156107ed575f80fd5b506107f66112ae565b6040516103939796959493929190613b0c565b348015610814575f80fd5b50610389610823366004613b94565b6113e6565b348015610833575f80fd5b506104457f000000000000000000000000000000000000000000000000000000000000000081565b348015610866575f80fd5b506103897fa891f76027ef63a24501b9dd3b0c779b49ad26d2328e9d423640209d1ad4fcc481565b348015610899575f80fd5b506108a2611455565b60405165ffffffffffff9091168152602001610393565b3480156108c4575f80fd5b506103dc6108d3366004613c21565b61145e565b3480156108e3575f80fd5b506103896108f23660046139ee565b6114d9565b348015610902575f80fd5b50612710610389565b348015610916575f80fd5b50610389610925366004613c42565b6114e6565b348015610935575f80fd5b5060035461ffff16610389565b34801561094d575f80fd5b506103dc61095c36600461382f565b611568565b34801561096c575f80fd5b506103dc61097b3660046133fb565b61157e565b34801561098b575f80fd5b505f610389565b34801561099d575f80fd5b506103896109ac3660046133fb565b611624565b3480156109bc575f80fd5b506003546109cb9061ffff1681565b60405161ffff9091168152602001610393565b3480156109e9575f80fd5b5061038961271081565b3480156109fe575f80fd5b50610389610a0d366004613612565b61163e565b348015610a1d575f80fd5b50610389610a2c366004613cf6565b611661565b348015610a3c575f80fd5b50610a50610a4b3660046133fb565b6116b3565b604051610393989796959493929190613d69565b348015610a6f575f80fd5b50610389610a7e366004613dd2565b61176e565b348015610a8e575f80fd5b506103897f7949bd92105c02f48ca245aa185f4a7a4d7185641d59b186ac64abeb44964f0c81565b348015610ac1575f80fd5b506103dc610ad036600461382f565b6117be565b348015610ae0575f80fd5b506103b06117d0565b348015610af4575f80fd5b506103897f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610b27575f80fd5b50610389610b36366004613e4e565b6117f0565b348015610b46575f80fd5b506103897f9a121fc10d6025acfc09275f9709796b68831733b5bbac0d510d13f85b1b730f81565b348015610b79575f80fd5b50610389610b883660046133fb565b6118a9565b348015610b98575f80fd5b507f0000000000000000000000000000000000000000000000000000000000000000610445565b5f60015b61ffff16905090565b60605f8054610bda90613e76565b80601f0160208091040260200160405190810160405280929190818152602001828054610c0690613e76565b8015610c515780601f10610c2857610100808354040283529160200191610c51565b820191905f5260205f20905b815481529060010190602001808311610c3457829003601f168201915b5050505050905090565b610c636118e4565b6040517f07a0033000000000000000000000000000000000000000000000000000000000815260048101839052602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906307a00330906044015b5f604051808303815f87803b158015610cf0575f80fd5b505af1158015610d02573d5f803e3d5ffd5b505050505050565b5f610d6f87610d698888604051602001610d25929190613ec7565b604051602081830303815290604052805190602001208787604051602001610d4e929190613f07565b6040516020818303038152906040528051906020012061191f565b8461197b565b610dc987878787878267ffffffffffffffff811115610d9057610d90613259565b604051908082528060200260200182016040528015610dc357816020015b6060815260200190600190039081610dae5790505b506119cc565b979650505050505050565b5f610dec610de0611b19565b60035461ffff16611b22565b905090565b5f610dc93388888888610e04888a613f40565b6119cc565b5f610e15858585611b4c565b5f610e1e611b19565b9050610e50845f81518110610e3557610e35613fb0565b602002602001015182600184610e4b919061400a565b611cef565b9695505050505050565b5f818152600160208190526040822054610e78919061ffff1661400a565b61ffff1692915050565b5f610eeb89610d698a8a604051602001610e9d929190613ec7565b604051602081830303815290604052805190602001208989604051602001610ec6929190613f07565b60405160208183030381529060405280519060200120610ee68989611de3565b611ec6565b610efd8989898989610e04898b613f40565b9998505050505050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610f3a57610dec611f1a565b507f000000000000000000000000000000000000000000000000000000000000000090565b5f80610bc3565b5f610e50610f7f610f778888611fb4565b868686611ffb565b878760405180602001604052805f81525061201f565b5f818152600160205260408120805462010000900460ff1615610fbb5750600792915050565b805461ffff165f819003610ffb576040517fd9c78e0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61100f61100a60018461400a565b6120ca565b90505f6001830161ffff16611022611b19565b61ffff1611159050815f03611049578061103d576006610e50565b60019695505050505050565b835477010000000000000000000000000000000000000000000000900461ffff16611074838261402c565b6127108660020154611086919061402c565b106110a45781611097576006610dc9565b6004979650505050505050565b6110b28361ffff831661402c565b6127108660010154856110c59190614043565b6110cf919061402c565b101580156110da5750815b156110ec575060019695505050505050565b5060039695505050505050565b6060610dec61217c565b5f61110d8261219c565b92915050565b61111b6118e4565b61112583836121ae565b61112f8382612229565b505050565b5f61113f8383611fb4565b9392505050565b5f61113f33848460405180602001604052805f81525061201f565b5f61117085610d698686611fb4565b61118a85858560405180602001604052805f81525061201f565b95945050505050565b5f61118a33868686868267ffffffffffffffff811115610d9057610d90613259565b5f61118a85856040516020016111cc929190613ec7565b604051602081830303815290604052805190602001208484604051602001610d4e929190613f07565b5f61118a33868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061201f92505050565b5f611244858585856122a4565b5095945050505050565b5f610dc98787604051602001611265929190613ec7565b60405160208183030381529060405280519060200120868660405160200161128e929190613f07565b60405160208183030381529060405280519060200120610ee68686611de3565b5f6060808280808381463082806040519080825280602002602001820160405280156112e4578160200160208202803683370190505b507f0f00000000000000000000000000000000000000000000000000000000000000949392919084805461131790613e76565b80601f016020809104026020016040519081016040528092919081815260200182805461134390613e76565b801561138e5780601f106113655761010080835404028352916020019161138e565b820191905f5260205f20905b81548152906001019060200180831161137157829003601f168201915b505050505094506040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525093929190965096509650965096509650965090919293949596565b5f61144961142c610f778a8a604051602001611403929190613ec7565b604051602081830303815290604052805190602001208989604051602001610d4e929190613f07565b898989898267ffffffffffffffff811115610d9057610d90613259565b98975050505050505050565b5f610bc3611b19565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146114cd576040517fb30b9d4300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114d6816124f3565b50565b5f61118a85858585612602565b5f61155a61154c610f778c8c604051602001611503929190613ec7565b604051602081830303815290604052805190602001208b8b60405160200161152c929190613f07565b60405160208183030381529060405280519060200120610ee68b8b611de3565b8b8b8b8b610e048b8d613f40565b9a9950505050505050505050565b6115706118e4565b61157a8282612229565b5050565b6115866118e4565b6040517f10bf5068000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906310bf5068906024015f604051808303815f87803b15801561160b575f80fd5b505af115801561161d573d5f803e3d5ffd5b5050505050565b5f81815260016020819052604082205461ffff1601610e78565b5f61118a835f8151811061165457611654613fb0565b602002602001015161219c565b5f61167287610d6988888888612602565b610dc987878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061201f92505050565b5f818152600160205260408120805461ffff1691908190819081908190819081906116de8960010190565b61ffff1697506116ed8a610f95565b600182015460028301548354929950909750955073ffffffffffffffffffffffffffffffffffffffff6301000000820416945061174c9061ffff8082169177010000000000000000000000000000000000000000000000900416611b22565b9250805f0160179054906101000a900461ffff16915050919395975091939597565b5f611449611781610f778a8a8a8a612602565b898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061201f92505050565b6117c66118e4565b61157a82826121ae565b60606040518060600160405280602d81526020016144ee602d9139905090565b6040517f3a46b1a800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390525f917f000000000000000000000000000000000000000000000000000000000000000090911690633a46b1a890604401602060405180830381865afa158015611885573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061113f9190614056565b5f818152600160205260408120805461113f9061ffff8082169177010000000000000000000000000000000000000000000000900416611b22565b33301461191d576040517f29c3b7ee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b604080517f9a121fc10d6025acfc09275f9709796b68831733b5bbac0d510d13f85b1b730f6020820152908101839052606081018290525f9061113f906080015b6040516020818303038152906040528051906020012061266c565b5f6119878484846126cd565b90505f81600581111561199c5761199c6137bb565b036119a75750505050565b6119b2848484612707565b156119bd5750505050565b6119c68161284f565b50505050565b5f84808203611a07576040517f75672da700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808414611a4f576040517ffa5dbe0800000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044015b60405180910390fd5b82518114611a965782516040517ffa5dbe08000000000000000000000000000000000000000000000000000000008152611a46918391600401918252602082015260400190565b5f5b81811015611b0d57611b0389898984818110611ab657611ab6613fb0565b90506020020135888885818110611acf57611acf613fb0565b9050602002016020810190611ae4919061406d565b878581518110611af657611af6613fb0565b602002602001015161201f565b9250600101611a98565b50509695505050505050565b5f610dec612a13565b5f612710611b3461100a60018661400a565b611b429061ffff851661402c565b61113f9190614086565b8251600114611b87576040517f83913ab500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16835f81518110611bb057611bb0613fb0565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614611c05576040517f82d5d76a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151600114611c40576040517f32143ab000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81518110611c5257611c52613fb0565b60200260200101515f14611c92576040517faa7feadc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600114611ccd576040517fc569313f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61112f815f81518110611ce257611ce2613fb0565b6020026020010151612a3b565b5f3415611d28576040517faa7feadc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8161ffff165f03611d65576040517f0797d96900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8161ffff168361ffff1610611db1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830192611da3908590612c3b565b9050805f0361113f57611d65565b6040517fb696436000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81818167ffffffffffffffff811115611dff57611dff613259565b604051908082528060200260200182016040528015611e28578160200160208202803683370190505b5090505f5b82811015611e9457858582818110611e4757611e47613fb0565b9050602002810190611e5991906140be565b604051611e6792919061411f565b6040518091039020828281518110611e8157611e81613fb0565b6020908102919091010152600101611e2d565b5080604051602001611ea6919061412e565b604051602081830303815290604052805190602001209250505092915050565b604080517fa891f76027ef63a24501b9dd3b0c779b49ad26d2328e9d423640209d1ad4fcc4602082015290810184905260608101839052608081018290525f90611f129060a001611960565b949350505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f5f1b5f604051611f4c9190614163565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810183905260ff821660608201525f9061113f90608001611960565b5f8061200986868686612daa565b925090506120168161284f565b50949350505050565b5f8061202a85610f95565b90506001816007811115612040576120406137bb565b1461207957806040517f88f40ea0000000000000000000000000000000000000000000000000000000008152600401611a469190613821565b5f858152600160205260409020546120bb9087907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61ffff91821601166117f0565b91506120168683878787612eb7565b6040517f5c7e5d5f00000000000000000000000000000000000000000000000000000000815261ffff821660048201525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690635c7e5d5f90602401602060405180830381865afa158015612158573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110d9190614056565b60606040518060a001604052806065815260200161448960659139905090565b5f61110d826121a9613069565b613079565b6040517fd48d84230000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff82811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063d48d842390604401610cd9565b6040517fb4d87a120000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff82811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063b4d87a1290604401610cd9565b5f806122b1868686611b4c565b6122b9613069565b90506122de845f815181106122d0576122d0613fb0565b602002602001015182613079565b5f8181526001602052604090205490925061ffff161561232a576040517f5c36267800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61245382826040805160c08101825261ffff92831681525f6020808301828152338486019081526003548716606086019081526080860185815260a087018681529986526001948590529690942094518554925191519451881677010000000000000000000000000000000000000000000000027fffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff96909616630100000002959095167fffffffffffffff00000000000000000000000000000000000000000000ffffff92151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000090941691909816179190911716949094171781559051918101919091559051600290910155565b7f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e0823388888a5167ffffffffffffffff81111561249257612492613259565b6040519080825280602002602001820160405280156124c557816020015b60608152602001906001900390816124b05790505b508987600181018b6040516124e2999897969594939291906142ae565b60405180910390a194509492505050565b6127108161ffff16118061250c575061010f61ffff8216105b15612559576040517f39aa1e1800000000000000000000000000000000000000000000000000000000815261ffff8216600482015261010f60248201526127106044820152606401611a46565b6003546040805161ffff928316815291831660208301527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a1600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661ffff83169081179091556040519081527fcae6f683fe1ab8ec2737e8d7cc5b306931ad2c39aa1701b65b3e4d9492bffa649060200160405180910390a150565b5f61118a7f7949bd92105c02f48ca245aa185f4a7a4d7185641d59b186ac64abeb44964f0c5f1b8686868660405161263b92919061411f565b60405190819003812061196094939291602001938452602084019290925260ff166040830152606082015260800190565b5f612675610f0a565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b5f805f6126da85856130cc565b90925090505f8260058111156126f2576126f26137bb565b146126fd5781610e50565b610e508682613110565b5f805f8573ffffffffffffffffffffffffffffffffffffffff16858560405160240161273492919061438a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1626ba7e00000000000000000000000000000000000000000000000000000000179052516127b591906143a2565b5f60405180830381855afa9150503d805f81146127ed576040519150601f19603f3d011682016040523d82523d5f602084013e6127f2565b606091505b509150915081801561280657506020815110155b8015610e50575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906128449083016020908101908401614056565b149695505050505050565b5f816005811115612862576128626137bb565b0361286a5750565b600181600581111561287e5761287e6137bb565b036128b5576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028160058111156128c9576128c96137bb565b03612900576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003816005811115612914576129146137bb565b0361294b576040517fbf4bf5b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600481600581111561295f5761295f6137bb565b03612996576040517fff551e8900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058160058111156129aa576129aa6137bb565b036129e1576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6213c680612a2663661bd35042614043565b612a309190614086565b610dec9060016143bd565b5f612a45826143d0565b82519091507fffffffff0000000000000000000000000000000000000000000000000000000082167fb4d87a1200000000000000000000000000000000000000000000000000000000148015612a9b5750604481145b158015612af657507fffffffff0000000000000000000000000000000000000000000000000000000082167fd48d842300000000000000000000000000000000000000000000000000000000148015612af45750604481145b155b8015612b5057507fffffffff0000000000000000000000000000000000000000000000000000000082167f519c958700000000000000000000000000000000000000000000000000000000148015612b4e5750606481145b155b8015612baa57507fffffffff0000000000000000000000000000000000000000000000000000000082167f07a0033000000000000000000000000000000000000000000000000000000000148015612ba85750604481145b155b8015612c0457507fffffffff0000000000000000000000000000000000000000000000000000000082167fb577512500000000000000000000000000000000000000000000000000000000148015612c025750602481145b155b1561112f576040517f1c49f4d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612c468383613079565b5f81815260016020526040902080549192509061ffff848116911614612c6f575f91505061110d565b6004612c7a83610f95565b6007811115612c8b57612c8b6137bb565b14612c99575f91505061110d565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff16620100001781556040517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90612cf69084815260200190565b60405180910390a15f803073ffffffffffffffffffffffffffffffffffffffff1686604051612d2591906143a2565b5f604051808303815f865af19150503d805f8114612d5e576040519150601f19603f3d011682016040523d82523d5f602084013e612d63565b606091505b509150915081612da157806040517f15fcd675000000000000000000000000000000000000000000000000000000008152600401611a4691906131be565b50505092915050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612ddf5750600390505f612eae565b8460ff16601b14158015612df757508460ff16601c14155b15612e075750600490505f612eae565b604080515f81526020810180835288905260ff871691810191909152606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612e57573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615612ea5575f81612ea9565b60015f5b915091505b94509492505050565b835f03612ef0576040517f8791239e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845290915290205460ff1615612f59576040517f7c9a1cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558260ff166001811115612fc557612fc56137bb565b6001811115612fd657612fd66137bb565b03612ff7575f8381526001602081905260409091200180548501905561300e565b5f8381526001602052604090206002018054850190555b8473ffffffffffffffffffffffffffffffffffffffff167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48484878560405161305a949392919061441f565b60405180910390a25050505050565b5f80613073611b19565b01905090565b5f82823060405160200161308f93929190614446565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209392505050565b5f8082516041146130e25750600290505f613109565b6020830151604084015160608501515f1a919061310187848484612daa565b945094505050505b9250929050565b5f8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461314b57600561113f565b505f92915050565b5f5b8381101561316d578181015183820152602001613155565b50505f910152565b5f815180845261318c816020860160208601613153565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61113f6020830184613175565b5f80604083850312156131e1575f80fd5b50508035926020909101359150565b803573ffffffffffffffffffffffffffffffffffffffff81168114613213575f80fd5b919050565b5f8083601f840112613228575f80fd5b50813567ffffffffffffffff81111561323f575f80fd5b6020830191508360208260051b8501011115613109575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156132cd576132cd613259565b604052919050565b5f82601f8301126132e4575f80fd5b813567ffffffffffffffff8111156132fe576132fe613259565b61332f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613286565b818152846020838601011115613343575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060808789031215613374575f80fd5b61337d876131f0565b9550602087013567ffffffffffffffff80821115613399575f80fd5b6133a58a838b01613218565b909750955060408901359150808211156133bd575f80fd5b6133c98a838b01613218565b909550935060608901359150808211156133e1575f80fd5b506133ee89828a016132d5565b9150509295509295509295565b5f6020828403121561340b575f80fd5b5035919050565b5f805f805f8060608789031215613427575f80fd5b863567ffffffffffffffff8082111561343e575f80fd5b61344a8a838b01613218565b90985096506020890135915080821115613462575f80fd5b61346e8a838b01613218565b90965094506040890135915080821115613486575f80fd5b5061349389828a01613218565b979a9699509497509295939492505050565b5f67ffffffffffffffff8211156134be576134be613259565b5060051b60200190565b5f82601f8301126134d7575f80fd5b813560206134ec6134e7836134a5565b613286565b8083825260208201915060208460051b87010193508684111561350d575f80fd5b602086015b8481101561353057613523816131f0565b8352918301918301613512565b509695505050505050565b5f82601f83011261354a575f80fd5b8135602061355a6134e7836134a5565b8083825260208201915060208460051b87010193508684111561357b575f80fd5b602086015b848110156135305780358352918301918301613580565b5f82601f8301126135a6575f80fd5b813560206135b66134e7836134a5565b82815260059290921b840181019181810190868411156135d4575f80fd5b8286015b8481101561353057803567ffffffffffffffff8111156135f6575f80fd5b6136048986838b01016132d5565b8452509183019183016135d8565b5f805f8060808587031215613625575f80fd5b843567ffffffffffffffff8082111561363c575f80fd5b613648888389016134c8565b9550602087013591508082111561365d575f80fd5b6136698883890161353b565b9450604087013591508082111561367e575f80fd5b5061368b87828801613597565b949793965093946060013593505050565b5f805f805f805f8060a0898b0312156136b3575f80fd5b6136bc896131f0565b9750602089013567ffffffffffffffff808211156136d8575f80fd5b6136e48c838d01613218565b909950975060408b01359150808211156136fc575f80fd5b6137088c838d01613218565b909750955060608b0135915080821115613720575f80fd5b61372c8c838d01613218565b909550935060808b0135915080821115613744575f80fd5b506137518b828c016132d5565b9150509295985092959890939650565b803560ff81168114613213575f80fd5b5f805f805f60a08688031215613785575f80fd5b8535945061379560208701613761565b93506137a360408701613761565b94979396509394606081013594506080013592915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6008811061381d577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b6020810161110d82846137e8565b5f8060408385031215613840575f80fd5b82359150613850602084016131f0565b90509250929050565b5f60208284031215613869575f80fd5b813567ffffffffffffffff81111561387f575f80fd5b611f12848285016132d5565b5f805f6060848603121561389d575f80fd5b833592506138ad602085016131f0565b91506138bb604085016131f0565b90509250925092565b5f80604083850312156138d5575f80fd5b8235915061385060208401613761565b5f805f80608085870312156138f8575f80fd5b613901856131f0565b93506020850135925061391660408601613761565b9150606085013567ffffffffffffffff811115613931575f80fd5b61393d878288016132d5565b91505092959194509250565b5f805f806040858703121561395c575f80fd5b843567ffffffffffffffff80821115613973575f80fd5b61397f88838901613218565b90965094506020870135915080821115613997575f80fd5b506139a487828801613218565b95989497509550505050565b5f8083601f8401126139c0575f80fd5b50813567ffffffffffffffff8111156139d7575f80fd5b602083019150836020828501011115613109575f80fd5b5f805f8060608587031215613a01575f80fd5b84359350613a1160208601613761565b9250604085013567ffffffffffffffff811115613a2c575f80fd5b6139a4878288016139b0565b5f805f8060808587031215613a4b575f80fd5b843567ffffffffffffffff80821115613a62575f80fd5b613a6e888389016134c8565b95506020870135915080821115613a83575f80fd5b613a8f8883890161353b565b94506040870135915080821115613aa4575f80fd5b613ab088838901613597565b93506060870135915080821115613ac5575f80fd5b5061393d878288016132d5565b5f815180845260208085019450602084015f5b83811015613b0157815187529582019590820190600101613ae5565b509495945050505050565b7fff000000000000000000000000000000000000000000000000000000000000008816815260e060208201525f613b4660e0830189613175565b8281036040840152613b588189613175565b905086606084015273ffffffffffffffffffffffffffffffffffffffff861660808401528460a084015282810360c084015261155a8185613ad2565b5f805f805f805f60a0888a031215613baa575f80fd5b873567ffffffffffffffff80821115613bc1575f80fd5b613bcd8b838c01613218565b909950975060208a0135915080821115613be5575f80fd5b50613bf28a828b01613218565b9096509450613c05905060408901613761565b9250606088013591506080880135905092959891949750929550565b5f60208284031215613c31575f80fd5b813561ffff8116811461113f575f80fd5b5f805f805f805f805f60c08a8c031215613c5a575f80fd5b893567ffffffffffffffff80821115613c71575f80fd5b613c7d8d838e01613218565b909b50995060208c0135915080821115613c95575f80fd5b613ca18d838e01613218565b909950975060408c0135915080821115613cb9575f80fd5b50613cc68c828d01613218565b9096509450613cd9905060608b01613761565b925060808a0135915060a08a013590509295985092959850929598565b5f805f805f8060a08789031215613d0b575f80fd5b613d14876131f0565b955060208701359450613d2960408801613761565b9350606087013567ffffffffffffffff80821115613d45575f80fd5b613d518a838b016139b0565b909550935060808901359150808211156133e1575f80fd5b65ffffffffffff8981168252881660208201526101008101613d8e60408301896137e8565b6060820196909652608081019490945273ffffffffffffffffffffffffffffffffffffffff9290921660a084015260c083015261ffff1660e0909101529392505050565b5f805f805f805f60c0888a031215613de8575f80fd5b87359650613df860208901613761565b9550604088013567ffffffffffffffff811115613e13575f80fd5b613e1f8a828b016139b0565b9096509450613e32905060608901613761565b92506080880135915060a0880135905092959891949750929550565b5f8060408385031215613e5f575f80fd5b613e68836131f0565b946020939093013593505050565b600181811c90821680613e8a57607f821691505b602082108103613ec1577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613ef4575f80fd5b8260051b80858437919091019392505050565b5f8184825b85811015613f355760ff613f1f83613761565b1683526020928301929190910190600101613f0c565b509095945050505050565b5f613f4d6134e7846134a5565b80848252602080830192508560051b850136811115613f6a575f80fd5b855b81811015613fa457803567ffffffffffffffff811115613f8a575f80fd5b613f9636828a016132d5565b865250938201938201613f6c565b50919695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b61ffff82811682821603908082111561402557614025613fdd565b5092915050565b808202811582820484141761110d5761110d613fdd565b8181038181111561110d5761110d613fdd565b5f60208284031215614066575f80fd5b5051919050565b5f6020828403121561407d575f80fd5b61113f82613761565b5f826140b9577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126140f1575f80fd5b83018035915067ffffffffffffffff82111561410b575f80fd5b602001915036819003821315613109575f80fd5b818382375f9101908152919050565b81515f9082906020808601845b838110156141575781518552938201939082019060010161413b565b50929695505050505050565b5f8083545f60018260011c9150600183168061418057607f831692505b602080841082036141b8577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b8180156141cc57600181146141ff5761422a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616895284151585028901965061422a565b5f8a8152602090205f5b868110156142225781548b820152908501908301614209565b505084890196505b509498975050505050505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156142a1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895261428f838351613175565b98840198925090830190600101614255565b5090979650505050505050565b5f6101208083018c8452602073ffffffffffffffffffffffffffffffffffffffff808e1660208701528360408701528293508c518084526101408701945060208e0193505f5b818110156143125784518316865294830194938301936001016142f4565b50505050508281036060840152614329818a613ad2565b9050828103608084015261433d8189614238565b905082810360a08401526143518188614238565b61ffff871660c0850152905061ffff851660e084015282810361010084015261437a8185613175565b9c9b505050505050505050505050565b828152604060208201525f611f126040830184613175565b5f82516143b3818460208701613153565b9190910192915050565b8082018082111561110d5761110d613fdd565b5f815160208301517fffffffff00000000000000000000000000000000000000000000000000000000808216935060048310156144175780818460040360031b1b83161693505b505050919050565b84815260ff84166020820152826040820152608060608201525f610e506080830184613175565b606081525f6144586060830186613175565b905061ffff8416602083015273ffffffffffffffffffffffffffffffffffffffff8316604083015294935050505056fe6d6f64653d65706f63682665706f6368556e6465726c79696e67536f757263653d626c6f636b54696d657374616d702665706f63685374617274696e6754696d657374616d703d313731333039393630302665706f6368506572696f643d31323936303030737570706f72743d616761696e73742c666f722671756f72756d3d666f7226737563636573733d71756f72756da26469706673582212206e4e4f61da996630edc3dbc3da375d7883f0096457851e1f33c6f873dd626fa564736f6c634300081700330000000000000000000000005983b89fa184f14917013b9c3062afd9434c5b03000000000000000000000000a0dafaeea4a1d44534e1b9227e19cae6358b80fe000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c000000000000000000000000b024ac5a7c6bc92fbacc8c3387e628a07e1da0160000000000000000000000000000000000000000000000000000000000001964","name":"EmergencyGovernor","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"shanghai","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"lib/ttg/lib/common/src/ERC712Extended.sol","source_code":"// 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"},{"file_path":"lib/ttg/lib/common/src/interfaces/IERC1271.sol","source_code":"// 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"},{"file_path":"lib/ttg/lib/common/src/interfaces/IERC20.sol","source_code":"// 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"},{"file_path":"lib/ttg/lib/common/src/interfaces/IERC20Extended.sol","source_code":"// 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"},{"file_path":"lib/ttg/lib/common/src/interfaces/IERC3009.sol","source_code":"// 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"},{"file_path":"lib/ttg/lib/common/src/interfaces/IERC712.sol","source_code":"// 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"},{"file_path":"lib/ttg/lib/common/src/interfaces/IERC712Extended.sol","source_code":"// 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"},{"file_path":"lib/ttg/lib/common/src/interfaces/IStatefulERC712.sol","source_code":"// 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"},{"file_path":"lib/ttg/lib/common/src/libs/SignatureChecker.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/abstract/BatchGovernor.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/abstract/ThresholdGovernor.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IGovernor } from \"./interfaces/IGovernor.sol\";\nimport { IThresholdGovernor } from \"./interfaces/IThresholdGovernor.sol\";\n\nimport { BatchGovernor } from \"./BatchGovernor.sol\";\n\n/**\n * @title  Extension for BatchGovernor with a threshold ratio used to determine quorum and yes-threshold requirements.\n * @author M^0 Labs\n */\nabstract contract ThresholdGovernor is IThresholdGovernor, BatchGovernor {\n    /* ============ Variables ============ */\n\n    /// @dev The minimum allowed threshold ratio.\n    uint16 internal constant _MIN_THRESHOLD_RATIO = 271;\n\n    /// @inheritdoc IThresholdGovernor\n    uint256 public constant ONE = 10_000;\n\n    /// @inheritdoc IThresholdGovernor\n    uint16 public thresholdRatio;\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Construct a new ThresholdGovernor 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     * @param  thresholdRatio_ The ratio of yes votes votes required for a proposal to meet quorum and succeed.\n     */\n    constructor(string memory name_, address voteToken_, uint16 thresholdRatio_) BatchGovernor(name_, voteToken_) {\n        _setThresholdRatio(thresholdRatio_);\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        uint16 latestPossibleVoteStart_ = _clock();\n\n        // Proposals have voteStart=N and voteEnd=N+1, and can be executed only during epochs N and N+1.\n        proposalId_ = _tryExecute(callDatas_[0], latestPossibleVoteStart_, latestPossibleVoteStart_ - 1);\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 returns (uint256 proposalId_) {\n        (proposalId_, ) = _propose(targets_, values_, callDatas_, description_);\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=quorum\";\n    }\n\n    /// @inheritdoc IThresholdGovernor\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            uint16 quorumNumerator_\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_ = _getQuorum(proposal_.voteStart, proposal_.thresholdRatio);\n        quorumNumerator_ = proposal_.thresholdRatio;\n    }\n\n    /// @inheritdoc IThresholdGovernor\n    function proposalQuorum(uint256 proposalId) external view returns (uint256) {\n        Proposal storage proposal_ = _proposals[proposalId];\n\n        return _getQuorum(proposal_.voteStart, proposal_.thresholdRatio);\n    }\n\n    /// @inheritdoc IGovernor\n    function quorum() external view returns (uint256) {\n        // NOTE: This only provides the quorum required for a proposal created at this moment.\n        return _getQuorum(_clock(), thresholdRatio);\n    }\n\n    /// @inheritdoc IThresholdGovernor\n    function quorumNumerator() external view returns (uint256) {\n        return thresholdRatio;\n    }\n\n    /// @inheritdoc IThresholdGovernor\n    function quorumDenominator() external pure returns (uint256) {\n        return ONE;\n    }\n\n    /// @inheritdoc IGovernor\n    function state(uint256 proposalId_) public view override(BatchGovernor, IGovernor) returns (ProposalState state_) {\n        Proposal storage proposal_ = _proposals[proposalId_];\n\n        if (proposal_.executed) return ProposalState.Executed;\n\n        uint16 voteStart_ = proposal_.voteStart;\n\n        if (voteStart_ == 0) revert ProposalDoesNotExist();\n\n        uint256 totalSupply_ = _getTotalSupply(voteStart_ - 1);\n        bool isVotingOpen_ = _clock() <= _getVoteEnd(voteStart_);\n\n        // If the total supply of Vote Tokens is 0 and the vote has not ended yet, the proposal is active.\n        // The proposal will expire once the voting period closes.\n        if (totalSupply_ == 0) return isVotingOpen_ ? ProposalState.Active : ProposalState.Expired;\n\n        uint16 thresholdRatio_ = proposal_.thresholdRatio;\n\n        // If proposal is currently succeeding, it has either succeeded or expired.\n        if (proposal_.yesWeight * ONE >= thresholdRatio_ * totalSupply_) {\n            return isVotingOpen_ ? ProposalState.Succeeded : ProposalState.Expired;\n        }\n\n        // If proposal can succeed while voting is open, it is active.\n        if (((totalSupply_ - proposal_.noWeight) * ONE >= thresholdRatio_ * totalSupply_) && isVotingOpen_) {\n            return ProposalState.Active;\n        }\n\n        return ProposalState.Defeated;\n    }\n\n    /* ============ Internal Interactive Functions ============ */\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: thresholdRatio,\n            noWeight: 0,\n            yesWeight: 0\n        });\n    }\n\n    /**\n     * @dev   Set the threshold ratio to be applied to determine the threshold/quorum for a proposal.\n     * @param newThresholdRatio_ The new threshold ratio.\n     */\n    function _setThresholdRatio(uint16 newThresholdRatio_) internal {\n        if (newThresholdRatio_ > ONE || newThresholdRatio_ < _MIN_THRESHOLD_RATIO) {\n            revert InvalidThresholdRatio(newThresholdRatio_, _MIN_THRESHOLD_RATIO, ONE);\n        }\n\n        emit QuorumNumeratorUpdated(thresholdRatio, newThresholdRatio_);\n        emit ThresholdRatioSet(thresholdRatio = newThresholdRatio_);\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Returns the quorum given a snapshot and quorum numerator.\n     * @param  voteStart_       The epoch at which the proposal will start collecting votes.\n     * @param  quorumNumerator_ The quorum numerator.\n     * @return quorum_          The quorum of yes voted needed for a successful proposal.\n     */\n    function _getQuorum(uint16 voteStart_, uint16 quorumNumerator_) internal view returns (uint256 quorum_) {\n        return (quorumNumerator_ * _getTotalSupply(voteStart_ - 1)) / ONE;\n    }\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 pure override returns (uint16) {\n        return 0;\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 1;\n    }\n}\n"},{"file_path":"lib/ttg/src/abstract/interfaces/IBatchGovernor.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/abstract/interfaces/IERC5805.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/abstract/interfaces/IERC6372.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/abstract/interfaces/IEpochBasedVoteToken.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/abstract/interfaces/IGovernor.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/abstract/interfaces/IThresholdGovernor.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IBatchGovernor } from \"./IBatchGovernor.sol\";\n\n/**\n * @title  Extension for BatchGovernor with a threshold ratio used to determine quorum and yes-threshold requirements.\n * @author M^0 Labs\n */\ninterface IThresholdGovernor is IBatchGovernor {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when the threshold ratio is set.\n     * @param  thresholdRatio The new threshold ratio.\n     */\n    event ThresholdRatioSet(uint16 thresholdRatio);\n\n    /**\n     * @notice Emitted when the quorum numerator is set.\n     * @param  oldQuorumNumerator The old quorum numerator.\n     * @param  newQuorumNumerator The new quorum numerator.\n     */\n    event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);\n\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when trying to set the threshold ratio above 100% or below 2.71%.\n     * @param  thresholdRatio    The threshold ratio being set.\n     * @param  minThresholdRatio The minimum allowed threshold ratio.\n     * @param  maxThresholdRatio The maximum allowed threshold ratio.\n     */\n    error InvalidThresholdRatio(uint256 thresholdRatio, uint256 minThresholdRatio, uint256 maxThresholdRatio);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns all data of a proposal with identifier `proposalId`.\n     * @param  proposalId      The unique identifier for 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 threshold/quorum of yes votes required for the proposal to succeed.\n     * @return quorumNumerator The threshold/quorum numerator used to calculate the 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            uint16 quorumNumerator\n        );\n\n    /**\n     * @notice Returns the threshold ratio to be applied to determine the success threshold for a proposal.\n     * @dev    For all intents and purposes, this is the same as `quorumNumerator`.\n     */\n    function thresholdRatio() external view returns (uint16);\n\n    /**\n     * @notice Returns the quorum of yes votes needed for a specific proposal to succeed.\n     * @param  proposalId The unique identifier for the proposal.\n     * @return The quorum of yes votes needed for the proposal to succeed.\n     */\n    function proposalQuorum(uint256 proposalId) external view returns (uint256);\n\n    /**\n     * @notice Returns the quorum numerator used to determine the quorum for a proposal.\n     * @dev    For all intents and purposes, this is the same as `thresholdRatio`.\n     */\n    function quorumNumerator() external view returns (uint256);\n\n    /// @notice Returns the quorum denominator used to determine the quorum for a proposal.\n    function quorumDenominator() external view returns (uint256);\n\n    /// @notice Returns the value used as 100%, to be used to correctly ascertain the threshold ratio.\n    function ONE() external pure returns (uint256);\n}\n"},{"file_path":"lib/ttg/src/interfaces/IEmergencyGovernor.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IThresholdGovernor } from \"../abstract/interfaces/IThresholdGovernor.sol\";\n\n/**\n * @title  An instance of a ThresholdGovernor with a unique and limited set of possible proposals.\n * @author M^0 Labs\n */\ninterface IEmergencyGovernor is IThresholdGovernor {\n    /* ============ Custom Errors ============ */\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 Standard Governor specified in the constructor is address(0).\n    error InvalidStandardGovernorAddress();\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 Zero Governor.\n    error NotZeroGovernor();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Sets the threshold ratio to use going forward for newly created proposals.\n     * @param  newThresholdRatio The new threshold ratio.\n     */\n    function setThresholdRatio(uint16 newThresholdRatio) 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 setStandardProposalFee(uint256 newProposalFee) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the address of the Registrar.\n    function registrar() 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 Zero Governor.\n    function zeroGovernor() external view returns (address);\n}\n"},{"file_path":"lib/ttg/src/interfaces/IRegistrar.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/interfaces/IStandardGovernor.sol","source_code":"// 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"},{"file_path":"lib/ttg/src/libs/PureEpochs.sol","source_code":"// 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"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"voteToken_","type":"address"},{"internalType":"address","name":"zeroGovernor_","type":"address"},{"internalType":"address","name":"registrar_","type":"address"},{"internalType":"address","name":"standardGovernor_","type":"address"},{"internalType":"uint16","name":"thresholdRatio_","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyVoted","type":"error"},{"inputs":[{"internalType":"uint256","name":"length1","type":"uint256"},{"internalType":"uint256","name":"length2","type":"uint256"}],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[],"name":"EmptyProposalIdsArray","type":"error"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"ExecutionFailed","type":"error"},{"inputs":[],"name":"InvalidCallData","type":"error"},{"inputs":[],"name":"InvalidCallDatasLength","type":"error"},{"inputs":[],"name":"InvalidRegistrarAddress","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSignatureLength","type":"error"},{"inputs":[],"name":"InvalidSignatureS","type":"error"},{"inputs":[],"name":"InvalidSignatureV","type":"error"},{"inputs":[],"name":"InvalidStandardGovernorAddress","type":"error"},{"inputs":[],"name":"InvalidTarget","type":"error"},{"inputs":[],"name":"InvalidTargetsLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"thresholdRatio","type":"uint256"},{"internalType":"uint256","name":"minThresholdRatio","type":"uint256"},{"internalType":"uint256","name":"maxThresholdRatio","type":"uint256"}],"name":"InvalidThresholdRatio","type":"error"},{"inputs":[],"name":"InvalidValue","type":"error"},{"inputs":[],"name":"InvalidValuesLength","type":"error"},{"inputs":[],"name":"InvalidVoteStart","type":"error"},{"inputs":[],"name":"InvalidVoteTokenAddress","type":"error"},{"inputs":[],"name":"InvalidZeroGovernorAddress","type":"error"},{"inputs":[],"name":"NotSelf","type":"error"},{"inputs":[],"name":"NotZeroGovernor","type":"error"},{"inputs":[],"name":"ProposalCannotBeExecuted","type":"error"},{"inputs":[],"name":"ProposalDoesNotExist","type":"error"},{"inputs":[],"name":"ProposalExists","type":"error"},{"inputs":[{"internalType":"enum IGovernor.ProposalState","name":"state","type":"uint8"}],"name":"ProposalInactive","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"SignerMismatch","type":"error"},{"inputs":[],"name":"ZeroVotingPower","type":"error"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"callDatas","type":"bytes[]"},{"indexed":false,"internalType":"uint256","name":"voteStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"voteEnd","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldQuorumNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorumNumerator","type":"uint256"}],"name":"QuorumNumeratorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"thresholdRatio","type":"uint16"}],"name":"ThresholdRatioSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"VoteCast","type":"event"},{"inputs":[],"name":"BALLOTS_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BALLOTS_WITH_REASON_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BALLOT_WITH_REASON_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"COUNTING_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"list_","type":"bytes32"},{"internalType":"address","name":"account_","type":"address"}],"name":"addToList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"},{"internalType":"uint8","name":"support_","type":"uint8"}],"name":"castVote","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"},{"internalType":"uint8","name":"support_","type":"uint8"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"castVoteBySig","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"voter_","type":"address"},{"internalType":"uint256","name":"proposalId_","type":"uint256"},{"internalType":"uint8","name":"support_","type":"uint8"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"castVoteBySig","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"},{"internalType":"uint8","name":"support_","type":"uint8"},{"internalType":"string","name":"reason_","type":"string"}],"name":"castVoteWithReason","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"voter_","type":"address"},{"internalType":"uint256","name":"proposalId_","type":"uint256"},{"internalType":"uint8","name":"support_","type":"uint8"},{"internalType":"string","name":"reason_","type":"string"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"castVoteWithReasonBySig","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"},{"internalType":"uint8","name":"support_","type":"uint8"},{"internalType":"string","name":"reason_","type":"string"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"castVoteWithReasonBySig","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"proposalIds_","type":"uint256[]"},{"internalType":"uint8[]","name":"supportList_","type":"uint8[]"}],"name":"castVotes","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"voter_","type":"address"},{"internalType":"uint256[]","name":"proposalIds_","type":"uint256[]"},{"internalType":"uint8[]","name":"supportList_","type":"uint8[]"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"castVotesBySig","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"proposalIds_","type":"uint256[]"},{"internalType":"uint8[]","name":"supportList_","type":"uint8[]"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"castVotesBySig","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"proposalIds_","type":"uint256[]"},{"internalType":"uint8[]","name":"supportList_","type":"uint8[]"},{"internalType":"string[]","name":"reasonList_","type":"string[]"}],"name":"castVotesWithReason","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"voter_","type":"address"},{"internalType":"uint256[]","name":"proposalIds_","type":"uint256[]"},{"internalType":"uint8[]","name":"supportList_","type":"uint8[]"},{"internalType":"string[]","name":"reasonList_","type":"string[]"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"castVotesWithReasonBySig","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"proposalIds_","type":"uint256[]"},{"internalType":"uint8[]","name":"supportList_","type":"uint8[]"},{"internalType":"string[]","name":"reasonList_","type":"string[]"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"castVotesWithReasonBySig","outputs":[{"internalType":"uint256","name":"weight_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields_","type":"bytes1"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"version_","type":"string"},{"internalType":"uint256","name":"chainId_","type":"uint256"},{"internalType":"address","name":"verifyingContract_","type":"address"},{"internalType":"bytes32","name":"salt_","type":"bytes32"},{"internalType":"uint256[]","name":"extensions_","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets_","type":"address[]"},{"internalType":"uint256[]","name":"values_","type":"uint256[]"},{"internalType":"bytes[]","name":"callDatas_","type":"bytes[]"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"execute","outputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"},{"internalType":"uint8","name":"support_","type":"uint8"}],"name":"getBallotDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"},{"internalType":"uint8","name":"support_","type":"uint8"},{"internalType":"string","name":"reason_","type":"string"}],"name":"getBallotWithReasonDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"proposalIds_","type":"uint256[]"},{"internalType":"uint8[]","name":"supportList_","type":"uint8[]"}],"name":"getBallotsDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"proposalIds_","type":"uint256[]"},{"internalType":"uint8[]","name":"supportList_","type":"uint8[]"},{"internalType":"string[]","name":"reasonList_","type":"string[]"}],"name":"getBallotsWithReasonDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"}],"name":"getProposal","outputs":[{"internalType":"uint48","name":"voteStart_","type":"uint48"},{"internalType":"uint48","name":"voteEnd_","type":"uint48"},{"internalType":"enum IGovernor.ProposalState","name":"state_","type":"uint8"},{"internalType":"uint256","name":"noVotes_","type":"uint256"},{"internalType":"uint256","name":"yesVotes_","type":"uint256"},{"internalType":"address","name":"proposer_","type":"address"},{"internalType":"uint256","name":"quorum_","type":"uint256"},{"internalType":"uint16","name":"quorumNumerator_","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"timepoint_","type":"uint256"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"voter","type":"address"}],"name":"hasVoted","outputs":[{"internalType":"bool","name":"hasVoted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"callData_","type":"bytes"}],"name":"hashProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes[]","name":"callDatas_","type":"bytes[]"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"hashProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"}],"name":"proposalDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"}],"name":"proposalProposer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"}],"name":"proposalSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"}],"name":"proposalVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets_","type":"address[]"},{"internalType":"uint256[]","name":"values_","type":"uint256[]"},{"internalType":"bytes[]","name":"callDatas_","type":"bytes[]"},{"internalType":"string","name":"description_","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"quorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"quorumNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registrar","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"list_","type":"bytes32"},{"internalType":"address","name":"accountToRemove_","type":"address"},{"internalType":"address","name":"accountToAdd_","type":"address"}],"name":"removeFromAndAddToList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"list_","type":"bytes32"},{"internalType":"address","name":"account_","type":"address"}],"name":"removeFromList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key_","type":"bytes32"},{"internalType":"bytes32","name":"value_","type":"bytes32"}],"name":"setKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newProposalFee_","type":"uint256"}],"name":"setStandardProposalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"newThresholdRatio_","type":"uint16"}],"name":"setThresholdRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"standardGovernor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId_","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum IGovernor.ProposalState","name":"state_","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"thresholdRatio","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voteToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zeroGovernor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0000000000000000000000005983b89fa184f14917013b9c3062afd9434c5b03000000000000000000000000a0dafaeea4a1d44534e1b9227e19cae6358b80fe000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c000000000000000000000000b024ac5a7c6bc92fbacc8c3387e628a07e1da0160000000000000000000000000000000000000000000000000000000000001964"}