{"file_path":"contracts/wlfi/WorldLibertyFinancialV4.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.24;\n\nimport {Math} from \"contracts/libraries/oz-v5/immutable/utils/math/Math.sol\";\nimport {VotesUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/governance/utils/VotesUpgradeable.sol\";\nimport {IWLFIStaking} from \"../wlfi-staking/interfaces/IWLFIStaking.sol\";\nimport {IWorldLibertyFinancialV4} from \"./interfaces/IWorldLibertyFinancialV4.sol\";\nimport {WorldLibertyFinancialV3} from \"./WorldLibertyFinancialV3.sol\";\n\n/**\n * @title WorldLibertyFinancialV4\n * @notice Counts wallet WLFI, unclaimed vesting, and staked principal with a fixed multiplier.\n * @dev Snapshot reads `getVotingPower`. Inherited `getVotes` follows the V3 rules. V4 reuses the existing proxy\n *      storage. The staking contract and staking multiplier are immutable in the implementation.\n * @custom:oz-upgrades-unsafe-allow missing-initializer\n */\ncontract WorldLibertyFinancialV4 is IWorldLibertyFinancialV4, WorldLibertyFinancialV3 {\n    // ==================================================\n    // =================== Constants ====================\n    // ==================================================\n\n    uint256 private constant _BPS_DENOMINATOR = 10_000;\n\n    // ==================================================\n    // ================ Immutable Fields ================\n    // ==================================================\n\n    /// @notice The staking contract whose active lock contributes voting power.\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n    IWLFIStaking public immutable override WLFI_STAKING;\n\n    /// @dev Fixed staking multiplier in basis points. `10_000` = 1x.\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n    uint32 private immutable _STAKING_VOTING_MULTIPLIER_BPS;\n\n    // ==================================================\n    // ================== Constructor ===================\n    // ==================================================\n\n    /**\n     * @notice Sets the inherited WLFI dependencies, staking contract, and fixed staking multiplier.\n     * @param _tradingStartTimestamp Unix timestamp, in seconds, when unrestricted WLFI trading starts.\n     * @param _registry Address of the inherited WLFI registry.\n     * @param _vester Address of the inherited WLFI vesting contract.\n     * @param _wlfiStaking Address of the WLFI staking contract.\n     * @param _multiplierBps Nonzero staking voting multiplier, in basis points. `10_000` = 1x.\n     * @custom:oz-upgrades-unsafe-allow constructor\n     */\n    constructor(\n        uint256 _tradingStartTimestamp,\n        address _registry,\n        address _vester,\n        address _wlfiStaking,\n        uint32 _multiplierBps\n    ) WorldLibertyFinancialV3(_tradingStartTimestamp, _registry, _vester) {\n        if (_wlfiStaking == address(0) || _wlfiStaking.code.length == 0) {\n            revert InvalidStakingContract();\n        }\n        if (_multiplierBps == 0) {\n            revert InvalidStakingVotingMultiplier();\n        }\n\n        WLFI_STAKING = IWLFIStaking(_wlfiStaking);\n        _STAKING_VOTING_MULTIPLIER_BPS = _multiplierBps;\n    }\n\n    // ==================================================\n    // ================ Public Functions ================\n    // ==================================================\n\n    /// @inheritdoc IWorldLibertyFinancialV4\n    function getVotingPower(address _account) public view override returns (uint256 votingPower) {\n        if (_account == address(0) || isVoterExcluded(_account) || isBlacklisted(_account)) {\n            return 0;\n        }\n\n        votingPower = balanceOf(_account) + VESTER.unclaimed(_account);\n\n        uint256 lockId = WLFI_STAKING.lockIdOf(_account);\n        if (lockId != 0) {\n            IWLFIStaking.LockInfo memory lockInfo = WLFI_STAKING.locks(lockId);\n            votingPower += _lockVotingPower(lockInfo.amount);\n        }\n\n        votingPower = Math.min(votingPower, MAX_VOTING_POWER);\n    }\n\n    /// @inheritdoc IWorldLibertyFinancialV4\n    function previewLockVotingPower(uint256 _amountWei) public view override returns (uint256 votingPower) {\n        return Math.min(_lockVotingPower(_amountWei), MAX_VOTING_POWER);\n    }\n\n    /// @inheritdoc IWorldLibertyFinancialV4\n    function delegate(address /* delegatee */) public pure override(IWorldLibertyFinancialV4, VotesUpgradeable) {\n        revert DelegationMovedToSnapshot();\n    }\n\n    /// @inheritdoc IWorldLibertyFinancialV4\n    function delegateBySig(\n        address /* delegatee */,\n        uint256 /* nonce */,\n        uint256 /* expiry */,\n        uint8 /* v */,\n        bytes32 /* r */,\n        bytes32 /* s */\n    ) public pure override(IWorldLibertyFinancialV4, VotesUpgradeable) {\n        revert DelegationMovedToSnapshot();\n    }\n\n    // ==================================================\n    // =============== Private Functions ================\n    // ==================================================\n\n    /// @dev Applies the fixed staking multiplier, independent of remaining lock duration.\n    function _lockVotingPower(uint256 _amountWei) private view returns (uint256) {\n        return Math.mulDiv(_amountWei, _STAKING_VOTING_MULTIPLIER_BPS, _BPS_DENOMINATOR);\n    }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106103f15760003560e01c80637df9a67411610215578063c455d4f611610125578063e1dfc884116100b8578063f13253bb11610087578063f13253bb1461091f578063f2fde38b14610927578063f36e05151461093a578063fbe2518f14610966578063fe575a871461096e57600080fd5b8063e1dfc884146108d1578063e30c3978146108e4578063e5195157146108ec578063f1127ed8146108ff57600080fd5b8063ce5a7e4e116100f4578063ce5a7e4e14610890578063d4593872146108a3578063dd1d1d9e146108ab578063dd62ed3e146108be57600080fd5b8063c455d4f61461083b578063c4d66de814610862578063c771909c14610875578063c7dac7041461087d57600080fd5b806395d89b41116101a8578063a9059cbb11610177578063a9059cbb146107e1578063b6274f3d146107f4578063bb4d443614610807578063bfc9c3591461081a578063c3cda5201461082d57600080fd5b806395d89b411461079757806395d9538d1461079f578063967f1cc6146107c65780639ab24eb0146107ce57600080fd5b80638da5cb5b116101e45780638da5cb5b146107545780638e539e8c1461075c57806391ddadf41461076f57806394d4827f1461078457600080fd5b80637df9a674146107005780637ecebe001461071357806384b0196e146107265780638682db371461074157600080fd5b80633a46b1a8116103105780635c19a95c116102a357806370a082311161027257806370a08231146106b7578063715018a6146106ca57806379ba5097146106d257806379cc6790146106da5780637adf1239146106ed57600080fd5b80635c19a95c146106595780635c975abb1461066c5780636fc9028e146106845780636fcfff451461069757600080fd5b806356f31c5d116102df57806356f31c5d146105e7578063587cde1e146105fa5780635a2cba271461061a5780635aa42d121461064657600080fd5b80633a46b1a8146105a657806342966c68146105b95780634bf5d7e9146105cc57806356c531b9146105d457600080fd5b806318160ddd116103885780632ad36687116103575780632ad3668714610552578063313ce567146105655780633254862e1461056c578063355e24bb1461057f57600080fd5b806318160ddd146104dc57806323b872dd14610503578063241f1c9914610516578063252f38671461053f57600080fd5b80630f861ca3116103c45780630f861ca314610494578063144220ea1461049e578063152439db146104b3578063172fe9e2146104c957600080fd5b806306433b1b146103f657806306fdde0314610433578063095ea7b3146104485780630c68ba2114610468575b600080fd5b61041d7f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce81565b60405161042a91906147bb565b60405180910390f35b61043b610981565b60405161042a919061481f565b61045b610456366004614871565b610a2a565b60405161042a91906148b6565b61045b6104763660046148c4565b6001600160a01b031660009081526001602052604090205460ff1690565b61049c610a44565b005b6104a6602d81565b60405161042a91906148ee565b6104bc60005481565b60405161042a9190614902565b61045b6104d7366004614924565b610a5e565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02546104bc565b61045b610511366004614945565b610a7c565b7f0000000000000000000000000000000000000000000000000000000068b58ac042101561045b565b61049c61054d3660046149e6565b610aa2565b61049c6105603660046148c4565b610ab3565b60126104a6565b61049c61057a366004614a77565b610acf565b61041d7f000000000000000000000000196fee96efeaad585483a6d950e70286b685192381565b6104bc6105b4366004614871565b610b21565b61049c6105c7366004614ab2565b610b3c565b61043b610b46565b61049c6105e2366004614ae6565b610bbe565b61049c6105f5366004614ab2565b610bd4565b61060d6106083660046148c4565b610c49565b60405161042a9190614b22565b61045b6106283660046148c4565b6001600160a01b031660009081526002602052604090205460ff1690565b61049c610654366004614ae6565b610c74565b61049c6106673660046148c4565b610c86565b6000805160206155d88339815191525460ff1661045b565b61045b6106923660046148c4565b610c9f565b6106aa6106a53660046148c4565b610dc3565b60405161042a9190614b3c565b6104bc6106c53660046148c4565b610dce565b61049c610e01565b61049c610e22565b61049c6106e8366004614871565b610e67565b61049c6106fb366004614b4a565b610e7c565b61049c61070e366004614945565b610f45565b6104bc6107213660046148c4565b610f58565b61072e610f81565b60405161042a9796959493929190614c61565b61049c61074f366004614ae6565b611005565b61060d611094565b6104bc61076a366004614ab2565b6110c9565b610777611138565b60405161042a9190614ceb565b61049c610792366004614945565b611147565b61043b61122f565b6104bc7f0000000000000000000000000000000000000000000000000000000068b58ac081565b61049c61126e565b6104bc6107dc3660046148c4565b611286565b61045b6107ef366004614871565b6113a6565b61049c610802366004614ae6565b6113b4565b6104bc6108153660046148c4565b6113c6565b6104bc6108283660046148c4565b61160d565b61049c610667366004614cf9565b61041d7f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb9502958381565b61049c6108703660046148c4565b6116b3565b61060d6117c9565b61049c61088b366004614ae6565b6117e5565b6104bc61089e366004614ab2565b611841565b61049c611857565b61049c6108b9366004614d83565b61185f565b6104bc6108cc366004614dde565b611968565b61049c6108df366004614ae6565b6119b2565b61060d6119ba565b6104bc6108fa3660046149e6565b6119e3565b61091261090d366004614e28565b611b2e565b60405161042a9190614e8e565b6104bc611b4c565b61049c6109353660046148c4565b611be5565b61045b6109483660046148c4565b6001600160a01b031660009081526003602052604090205460ff1690565b6104a6602f81565b61045b61097c3660046148c4565b611c6a565b606060006000805160206155988339815191525b90508060030180546109a690614eb2565b80601f01602080910402602001604051908101604052809291908181526020018280546109d290614eb2565b8015610a1f5780601f106109f457610100808354040283529160200191610a1f565b820191906000526020600020905b815481529060010190602001808311610a0257829003601f168201915b505050505091505090565b600033610a38818585611c96565b60019150505b92915050565b610a4c611ca3565b610a54611cd5565b610a5c611d05565b565b600060028260ff1610158015610a3e575050601460ff909116111590565b600033610a8a858285611d54565b610a95858585611da1565b60019150505b9392505050565b33610aae818484611e00565b505050565b610abb611ca3565b610acc610ac6611ebd565b82611f1d565b50565b610ad7611ca3565b610adf611f91565b60005b81811015610aae57610b19838383818110610aff57610aff614ede565b9050602002016020810190610b1491906148c4565b611fc2565b600101610ae2565b600060405163d623472560e01b815260040160405180910390fd5b610acc338261267e565b6060610b506126b4565b65ffffffffffff16610b60611138565b65ffffffffffff1614610b86576040516301bfc1c560e61b815260040160405180910390fd5b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b610bc6611ca3565b610bd082826126bf565b5050565b610bdc611ca3565b6b1027e72f1f12813088000000811115610c095760405163cec0812160e01b815260040160405180910390fd5b60008190556040517fe891886eac9e583940fb0844098689693a4d105206ec1f789d119b4314383b9590610c3e908390614902565b60405180910390a150565b6001600160a01b03908116600090815260008051602061557883398151915260205260409020541690565b610c7c612724565b610bd08282612756565b604051638510efe160e01b815260040160405180910390fd5b60405163d68b948d60e01b81526000906001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce169063d68b948d90610cee908590600401614b22565b602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190614eff565b1580610a3e57506040516325b6123360e11b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690634b6c246690610d82908590600401614b22565b602060405180830381865afa158015610d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190614eff565b6000610a3e826127c9565b6000806000805160206155988339815191525b6001600160a01b0390931660009081526020939093525050604090205490565b610e09611ca3565b60405163d623472560e01b815260040160405180910390fd5b3380610e2c6119ba565b6001600160a01b031614610e5e578060405163118cdaa760e01b8152600401610e559190614b22565b60405180910390fd5b610acc8161281a565b610e72823383611d54565b610bd0828261267e565b610e84611ca3565b841580610e915750848314155b80610e9c5750828114155b15610eba57604051630e52390960e41b815260040160405180910390fd5b60005b85811015610f3c57610f34878783818110610eda57610eda614ede565b9050602002016020810190610eef91906148c4565b868684818110610f0157610f01614ede565b9050602002016020810190610f1691906148c4565b858585818110610f2857610f28614ede565b90506020020135612852565b600101610ebd565b50505050505050565b610f4d611ca3565b610aae838383612852565b6000807f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00610de1565b600060608082808083816000805160206155b88339815191528054909150158015610fae57506001810154155b610fca5760405162461bcd60e51b8152600401610e5590614f20565b610fd2612d1f565b610fda612d5e565b60408051600080825260208201909252600f60f81b9c939b5091995046985030975095509350915050565b61100d611ca3565b6001600160a01b03821661103457604051630da30f6560e31b815260040160405180910390fd5b6001600160a01b03821660008181526001602052604090819020805460ff1916841515179055517fca139a0ba60fe6426dd1d713a05ec0c645224f72d7a9912d64163974672dd410906110889084906148b6565b60405180910390a25050565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005b546001600160a01b031692915050565b6000600080516020615578833981519152816110e3611138565b90508065ffffffffffff168410611111578381604051637669fc0f60e11b8152600401610e55929190614f69565b61112761111d85612d76565b6002840190612da8565b6001600160d01b0316949350505050565b60006111426126b4565b905090565b61114f611ca3565b6001600160a01b03831661117657604051630da30f6560e31b815260040160405180910390fd5b8060000361119757604051632a9ffab760e21b815260040160405180910390fd5b6040516370a0823160e01b81526000906001600160a01b038416906370a08231906111c6903090600401614b22565b602060405180830381865afa1580156111e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112079190614f8f565b905080821115611215578091505b6112296001600160a01b0384168584612e5e565b50505050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace048054606091600080516020615598833981519152916109a690614eb2565b611276611ca3565b61127e611f91565b610a5c612eb6565b6001600160a01b03811660009081526003602052604081205460ff16806112b157506112b182611c6a565b156112be57506000919050565b60405163282de9ed60e11b81526000906001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169063505bd3da9061130d908690600401614b22565b602060405180830381865afa15801561132a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134e9190614f8f565b61135784612eff565b6113619190614fc6565b9050600061136e84610c49565b6001600160a01b0316036113925761138583610dce565b61138f9082614fc6565b90505b600054811115610a3e575050600054919050565b600033610a38818585611da1565b6113bc611ca3565b610bd08282612f5f565b60006001600160a01b03821615806113f657506001600160a01b03821660009081526003602052604090205460ff165b80611405575061140582611c6a565b1561141257506000919050565b60405163282de9ed60e11b81526001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169063505bd3da9061145e908590600401614b22565b602060405180830381865afa15801561147b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149f9190614f8f565b6114a883610dce565b6114b29190614fc6565b905060007f000000000000000000000000196fee96efeaad585483a6d950e70286b68519236001600160a01b031663300e1db8846040518263ffffffff1660e01b81526004016115029190614b22565b602060405180830381865afa15801561151f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115439190614f8f565b905080156116015760405163f4dadc6160e01b81526000906001600160a01b037f000000000000000000000000196fee96efeaad585483a6d950e70286b6851923169063f4dadc619061159a908590600401614902565b60a060405180830381865afa1580156115b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115db91906150d6565b90506115f381600001516001600160801b031661321e565b6115fd9084614fc6565b9250505b610a9b82600054613253565b6000611617611f91565b61161f611ca3565b604051632e6639a560e21b81526001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169063b998e6949061166b908590600401614b22565b6020604051808303816000875af115801561168a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190614f8f565b919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff16806116fc575080546001600160401b03808416911610155b1561171a5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b178155611765611746610981565b604051806040016040528060018152602001601960f91b815250613269565b600061176f611ebd565b905061177b8185611f1d565b50805468ff0000000000000000191681556040517fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2906117bc908490615106565b60405180910390a1505050565b60006117d3611ebd565b600101546001600160a01b0316919050565b6117ed611ca3565b6001600160a01b03821660008181526002602052604090819020805460ff1916841515179055517fe4b88447f604c5e795f270c2758f4822062b56a3c2fc8b75394b077ba1dbf8ff906110889084906148b6565b6000610a3e61184f8361321e565b600054613253565b611276612724565b611867611f91565b334284101561188957604051631ab7da6b60e01b815260040160405180910390fd5b60006118de7f33a518e58b94b9604db5b08c90c70e148297bb153fdbe2be45395ac5b6e4640b83876040516020016118c393929190615114565b6040516020818303038152906040528051906020012061327b565b90506119208185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132a892505050565b6001600160a01b03166119316117c9565b6001600160a01b03161461195857604051638baa579f60e01b815260040160405180910390fd5b61196182611fc2565b5050505050565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b610c7c611ca3565b6000807f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c006110b9565b60006119ed611f91565b336119f9818585611e00565b60405163402914f560e01b81526001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169063402914f590611a45908490600401614b22565b602060405180830381865afa158015611a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a869190614f8f565b600003611a97576000915050610a3e565b604051632e6639a560e21b81527f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb950295836001600160a01b03169063b998e69490611ae3903390600401614b22565b6020604051808303816000875af1158015611b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b269190614f8f565b949350505050565b6040805180820190915260008082526020820152610a9b83836132d2565b6000611b56611f91565b604051632e6639a560e21b81527f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb950295836001600160a01b03169063b998e69490611ba2903390600401614b22565b6020604051808303816000875af1158015611bc1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111429190614f8f565b611bed611ca3565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080546001600160a01b0319166001600160a01b0383169081178255611c31611094565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b6000611c74611ebd565b6001600160a01b03909216600090815260209290925250604090205460ff1690565b610aae8383836001613335565b33611cac611094565b6001600160a01b031614610a5c573360405163118cdaa760e01b8152600401610e559190614b22565b6000805160206155d88339815191525460ff16610a5c57604051638dfc202b60e01b815260040160405180910390fd5b611d0d611cd5565b6000805160206155d8833981519152805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051610c3e9190614b22565b6000611d608484611968565b905060001981146112295781811015611d9257828183604051637dc7a0d960e11b8152600401610e559392919061513c565b61122984848484036000613335565b6001600160a01b038316611dcb576000604051634b637e8f60e11b8152600401610e559190614b22565b6001600160a01b038216611df557600060405163ec442f0560e01b8152600401610e559190614b22565b610aae838383613367565b6000611e387f214b6837b0cb36c3dfa2494ae052b630f55f351d9e069e1c5920491aa344a514856040516020016118c3929190615157565b9050611e7a8184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132a892505050565b6001600160a01b0316611e8b6117c9565b6001600160a01b031614611eb257604051638baa579f60e01b815260040160405180910390fd5b611229846000612f5f565b60008060ff19611eee60017f5d14c3535674e7f5942e30e2a55bfc241c205a216ca5bfc40c567afac5d67ad3615172565b604051602001611efe9190614902565b60408051601f1981840301815291905280516020909101201692915050565b6001600160a01b038116611f445760405163371685cf60e11b815260040160405180910390fd5b6001820180546001600160a01b0319166001600160a01b0383169081179091556040517fdc26eaa07c3e782e27ef385f6a52197f10505eed55db43e69a3d522714d0875a90600090a25050565b6000805160206155d88339815191525460ff1615610a5c5760405163d93c066560e01b815260040160405180910390fd5b60405163d68b948d60e01b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce169063d68b948d9061200e908490600401614b22565b602060405180830381865afa15801561202b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204f9190614eff565b61206c57604051630da30f6560e31b815260040160405180910390fd5b604051630eb2335d60e21b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690633ac8cd74906120b8908490600401614b22565b602060405180830381865afa1580156120d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f99190614eff565b15612119578060405163583c441960e11b8152600401610e559190614b22565b604051630b81b86360e41b81526001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169063b81b863090612165908490600401614b22565b602060405180830381865afa158015612182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a69190614f8f565b6000036121c8578060405163482aa09560e01b8152600401610e559190614b22565b604051635d0ecba760e11b81526000906001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce169063ba1d974e90612217908590600401614b22565b602060405180830381865afa158015612234573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122589190615190565b905060ff8116602d148061226f575060ff8116602f145b1561228c576040516217bf7f60e81b815260040160405180910390fd5b600060001960ff8316016122a25750602d6122d3565b6122ab82610a5e565b156122b85750602f6122d3565b8160405163643a2f0760e11b8152600401610e5591906148ee565b602e1960ff82160161253657604051630b81b86360e41b81526000906001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169063b81b86309061232e908790600401614b22565b602060405180830381865afa15801561234b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236f9190614f8f565b9050600061237e600a836151c7565b905060007f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb950295836001600160a01b031663c884ef83876040518263ffffffff1660e01b81526004016123ce9190614b22565b602060405180830381865afa1580156123eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240f9190614f8f565b90508015612432578560405163559073f160e11b8152600401610e559190614b22565b60405163d89e836f60e01b81526001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169063d89e836f9061248090899086906004016151db565b600060405180830381600087803b15801561249a57600080fd5b505af11580156124ae573d6000803e3d6000fd5b505060405163d89e836f60e01b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce16925063d89e836f915061250090899086906004016151db565b600060405180830381600087803b15801561251a57600080fd5b505af115801561252e573d6000803e3d6000fd5b505050505050505b604051631221980760e11b81526001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb950295831690632443300e9061258490869085906004016151f6565b600060405180830381600087803b15801561259e57600080fd5b505af11580156125b2573d6000803e3d6000fd5b5050604051631221980760e11b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce169250632443300e915061260490869085906004016151f6565b600060405180830381600087803b15801561261e57600080fd5b505af1158015612632573d6000803e3d6000fd5b50505050826001600160a01b03167ffc5a3510b90b1cebfceb2e53f8b658f2f4b4743ac89a379aa32f6250ebae35458383604051612671929190615211565b60405180910390a2505050565b6001600160a01b0382166126a8576000604051634b637e8f60e11b8152600401610e559190614b22565b610bd082600083613367565b600061114243612d76565b80156126d0576126d082600061364d565b6001600160a01b03821660008181526003602052604090819020805460ff1916841515179055517f662fe17a45a2827abeda36082dde83f496af4ace698c1db04e760bc78bd8be03906110889084906148b6565b3360008181526001602052604090205460ff16610acc5780604051635a968dab60e01b8152600401610e559190614b22565b80156127675761276782600061364d565b80612770611ebd565b6001600160a01b0384166000818152602092909252604091829020805460ff191693151593909317909255517f5019745a56bcdd97726f5b35a7bfcb97ffa4e40b51bc2f6f764c6671e1bef6d4906110889084906148b6565b6001600160a01b03811660009081527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d01602052604081205460008051602061557883398151915290610a9b906136b9565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080546001600160a01b0319168155610bd0826136e5565b600061285c611ebd565b6001600160a01b03851660009081526020829052604090205490915060ff16801561288c5761288c856000612756565b604051630eb2335d60e21b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690633ac8cd74906128d8908890600401614b22565b602060405180830381865afa1580156128f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129199190614eff565b801561292d57508261292a86610dce565b14155b1561294b57604051632dfd9c3960e01b815260040160405180910390fd5b60405163d68b948d60e01b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce169063d68b948d90612997908790600401614b22565b602060405180830381865afa1580156129b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129d89190614eff565b156129fa57848460405163314b500b60e21b8152600401610e5592919061521f565b8215612a1457612a0a858461267e565b612a148484613756565b604051630eb2335d60e21b81526000906001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690633ac8cd7490612a63908990600401614b22565b602060405180830381865afa158015612a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa49190614eff565b15612b3257506040516302612aeb60e21b81526001906001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690630984abac90612afb908990899060040161521f565b600060405180830381600087803b158015612b1557600080fd5b505af1158015612b29573d6000803e3d6000fd5b50505050612cc9565b6040516325b6123360e11b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690634b6c246690612b7e908990600401614b22565b602060405180830381865afa158015612b9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbf9190614eff565b15612cc957506040516302612aeb60e21b81526001906001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690630984abac90612c16908990899060040161521f565b600060405180830381600087803b158015612c3057600080fd5b505af1158015612c44573d6000803e3d6000fd5b50506040516302612aeb60e21b81526001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169250630984abac9150612c96908990899060040161521f565b600060405180830381600087803b158015612cb057600080fd5b505af1158015612cc4573d6000803e3d6000fd5b505050505b8115612cda57612cda866001612756565b7f7010a46c57b41359be039fda242f641df5204a59c81af3f06adbf8317100400686868684604051612d0f949392919061522d565b60405180910390a1505050505050565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060916000805160206155b8833981519152916109a690614eb2565b606060006000805160206155b8833981519152610995565b600065ffffffffffff821115612da4576030826040516306dfcc6560e41b8152600401610e5592919061527f565b5090565b815460009081816005811115612e07576000612dc38461378c565b612dcd9085615172565b60008881526020902090915081015465ffffffffffff9081169087161015612df757809150612e05565b612e02816001614fc6565b92505b505b6000612e1587878585613874565b90508015612e5057612e3a87612e2c600184615172565b600091825260209091200190565b54600160301b90046001600160d01b0316612e53565b60005b979650505050505050565b610aae83846001600160a01b031663a9059cbb8585604051602401612e849291906151db565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506138d6565b612ebe611f91565b6000805160206155d8833981519152805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833611d47565b6001600160a01b03811660009081527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d016020526040812060008051602061557883398151915290612f4f90613930565b6001600160d01b03169392505050565b604051634f1908cd60e01b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690634f1908cd90612fab908590600401614b22565b600060405180830381600087803b158015612fc557600080fd5b505af1158015612fd9573d6000803e3d6000fd5b5050604051635d0ecba760e11b8152600092506001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce16915063ba1d974e9061302c908690600401614b22565b602060405180830381865afa158015613049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061306d9190615190565b905060007f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce6001600160a01b0316632402f27f856040518263ffffffff1660e01b81526004016130bd9190614b22565b602060405180830381865afa1580156130da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130fe91906152a7565b90508261122957613131847f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb950295836000611c96565b613165847f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583836001600160701b0316611c96565b60405163b5f3b57d60e01b81526001600160a01b037f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583169063b5f3b57d906131b5908790869086906004016152d7565b600060405180830381600087803b1580156131cf57600080fd5b505af11580156131e3573d6000803e3d6000fd5b50505050613211847f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583611968565b15611229576112296152ff565b6000610a3e827f000000000000000000000000000000000000000000000000000000000000271063ffffffff16612710613969565b60008183106132625781610a9b565b5090919050565b613271613a2d565b610bd08282613a76565b6000610a3e613288613ad7565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000806132b88686613ae1565b9250925092506132c88282613b2e565b5090949350505050565b604080518082018252600080825260208083018290526001600160a01b03861682527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d0190529190912060008051602061557883398151915290611b269084613be5565b3361333f81613c55565b8461334981613c55565b8461335381613c55565b61335b611f91565b610f3c87878787613cb1565b3361337181613c55565b8361337b81613c55565b8361338581613c55565b306001600160a01b038616036133ae57604051630da30f6560e31b815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000068b58ac04210156134bb57337f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb950295836001600160a01b031614801561343f57507f00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb950295836001600160a01b0316856001600160a01b0316145b80613462575061344d611094565b6001600160a01b0316336001600160a01b0316145b1561347757613472868686613d96565b613645565b6001600160a01b03861660009081526002602052604090205460ff166134b05760405163af423a6f60e01b815260040160405180910390fd5b613472868686613d96565b604051630eb2335d60e21b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690633ac8cd7490613507908990600401614b22565b602060405180830381865afa158015613524573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135489190614eff565b801561356d5750613557611094565b6001600160a01b0316336001600160a01b031614155b1561358d578560405163583c441960e11b8152600401610e559190614b22565b604051630eb2335d60e21b81526001600160a01b037f0000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce1690633ac8cd74906135d9908890600401614b22565b602060405180830381865afa1580156135f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061361a9190614eff565b1561363a578460405163583c441960e11b8152600401610e559190614b22565b613645868686613d96565b505050505050565b3361365781613c55565b8261366181613c55565b8261366b81613c55565b613673611f91565b6001600160a01b03851660009081526003602052604090205460ff16156136af578460405163064a023360e51b8152600401610e559190614b22565b6119618585613da9565b600063ffffffff821115612da4576020826040516306dfcc6560e41b8152600401610e5592919061527f565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001600160a01b03821661378057600060405163ec442f0560e01b8152600401610e559190614b22565b610bd060008383613367565b60008160000361379e57506000919050565b600060016137ab84613e33565b901c6001901b905060018184816137c4576137c46151b1565b048201901c905060018184816137dc576137dc6151b1565b048201901c905060018184816137f4576137f46151b1565b048201901c9050600181848161380c5761380c6151b1565b048201901c90506001818481613824576138246151b1565b048201901c9050600181848161383c5761383c6151b1565b048201901c90506001818481613854576138546151b1565b048201901c9050610a9b8182858161386e5761386e6151b1565b04613253565b60005b818310156138ce57600061388b8484613ec7565b60008781526020902090915065ffffffffffff86169082015465ffffffffffff1611156138ba578092506138c8565b6138c5816001614fc6565b93505b50613877565b509392505050565b60006138eb6001600160a01b03841683613ee2565b9050805160001415801561391057508080602001905181019061390e9190614eff565b155b15610aae5782604051635274afe760e01b8152600401610e559190614b22565b805460009080156139605761394a83612e2c600184615172565b54600160301b90046001600160d01b0316610a9b565b60009392505050565b60008383028160001985870982811083820303915050806000036139a057838281613996576139966151b1565b0492505050610a9b565b8084116139c05760405163227bc15360e01b815260040160405180910390fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610a5c57604051631afcd79f60e31b815260040160405180910390fd5b613a7e613a2d565b6000805160206155b88339815191527fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102613ab884826153a6565b5060038101613ac783826153a6565b5060008082556001909101555050565b6000611142613ef0565b60008060008351604103613b1b5760208401516040850151606086015160001a613b0d88828585613f54565b955095509550505050613b27565b50508151600091506002905b9250925092565b6000826003811115613b4257613b42615468565b03613b4b575050565b6001826003811115613b5f57613b5f615468565b03613b7d5760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115613b9157613b91615468565b03613bb15760405163fce698f760e01b8152610e55908290600401614902565b6003826003811115613bc557613bc5615468565b03610bd057806040516335e2f38360e21b8152600401610e559190614902565b6040805180820190915260008082526020820152826000018263ffffffff1681548110613c1457613c14614ede565b60009182526020918290206040805180820190915291015465ffffffffffff81168252600160301b90046001600160d01b0316918101919091529392505050565b6001600160a01b03811615801590613c8e5750613c70611ebd565b6001600160a01b0382166000908152602091909152604090205460ff165b15610acc57806040516001620b633d60e31b03198152600401610e559190614b22565b6000805160206155988339815191526001600160a01b038516613cea57600060405163e602df0560e01b8152600401610e559190614b22565b6001600160a01b038416613d14576000604051634a1406b160e11b8152600401610e559190614b22565b6001600160a01b0380861660009081526001830160209081526040808320938816835292905220839055811561196157836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051613d879190614902565b60405180910390a35050505050565b613d9e611f91565b610aae838383614016565b6000805160206155788339815191526000613dc384610c49565b6001600160a01b0385811660008181526020869052604080822080546001600160a01b031916898616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46112298184613e2e87614096565b6140a1565b600080608083901c15613e4857608092831c92015b604083901c15613e5a57604092831c92015b602083901c15613e6c57602092831c92015b601083901c15613e7e57601092831c92015b600883901c15613e9057600892831c92015b600483901c15613ea257600492831c92015b600283901c15613eb457600292831c92015b600183901c15610a3e5760010192915050565b6000613ed660028484186151c7565b610a9b90848416614fc6565b6060610a9b83836000614209565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f613f1b6142a6565b613f23614310565b4630604051602001613f3995949392919061547e565b60405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115613f8f575060009150600390508261400c565b600060018888888860405160008152602001604052604051613fb494939291906154c0565b6020604051602081039080840390855afa158015613fd6573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166140025750600092506001915082905061400c565b9250600091508190505b9450945094915050565b614021838383614354565b6001600160a01b03831661408b5760006140597f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025490565b90506001600160d01b0380821115614088578181604051630e58ae9360e11b8152600401610e559291906154f5565b50505b610aae83838361447d565b6000610a3e82610dce565b6000805160206155788339815191526001600160a01b03848116908416148015906140cc5750600082115b15611229576001600160a01b0384161561416d576001600160a01b038416600090815260018201602052604081208190614111906144ef61410c876144fb565b61452a565b6001600160d01b031691506001600160d01b03169150856001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516141629291906154f5565b60405180910390a250505b6001600160a01b03831615611229576001600160a01b0383166000908152600182016020526040812081906141a89061456361410c876144fb565b6001600160d01b031691506001600160d01b03169150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516141f99291906154f5565b60405180910390a2505050505050565b60608147101561422e573060405163cd78605960e01b8152600401610e559190614b22565b600080856001600160a01b0316848660405161424a9190615525565b60006040518083038185875af1925050503d8060008114614287576040519150601f19603f3d011682016040523d82523d6000602084013e61428c565b606091505b509150915061429c86838361456f565b9695505050505050565b60006000805160206155b8833981519152816142c0612d1f565b8051909150156142d857805160209091012092915050565b815480156142e7579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b60006000805160206155b88339815191528161432a612d5e565b80519091501561434257805160209091012092915050565b600182015480156142e7579392505050565b6000805160206155988339815191526001600160a01b03841661439057818160020160008282546143859190614fc6565b909155506143ef9050565b6001600160a01b038416600090815260208290526040902054828110156143d05784818460405163391434e360e21b8152600401610e559392919061513c565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b03831661440d57600281018054839003905561442c565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161446f9190614902565b60405180910390a350505050565b6000805160206155788339815191526001600160a01b0384166144b0576144ad8160020161456361410c856144fb565b50505b6001600160a01b0383166144d4576144d1816002016144ef61410c856144fb565b50505b6112296144e085610c49565b6144e985610c49565b846140a1565b6000610a9b8284615531565b60006001600160d01b03821115612da45760d0826040516306dfcc6560e41b8152600401610e5592919061527f565b600080614556614538611138565b61454e61454488613930565b868863ffffffff16565b8791906145c2565b915091505b935093915050565b6000610a9b8284615554565b6060826145845761457f826145d0565b610a9b565b815115801561459b57506001600160a01b0384163b155b156145bb5783604051639996b31560e01b8152600401610e559190614b22565b5080610a9b565b6000806145568585856145f9565b8051156145e05780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b82546000908190801561471857600061461787612e2c600185615172565b60408051808201909152905465ffffffffffff808216808452600160301b9092046001600160d01b03166020840152919250908716101561466b57604051632520601d60e01b815260040160405180910390fd5b805165ffffffffffff8088169116036146b7578461468e88612e2c600186615172565b80546001600160d01b0392909216600160301b0265ffffffffffff909216919091179055614708565b6040805180820190915265ffffffffffff80881682526001600160d01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160301b029216919091179101555b60200151925083915061455b9050565b50506040805180820190915265ffffffffffff80851682526001600160d01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160301b02919093161792019190915590508161455b565b6000610a3e6001600160a01b03831661478a565b90565b6001600160a01b031690565b6000610a3e82614773565b6000610a3e82614796565b6147b5816147a1565b82525050565b60208101610a3e82846147ac565b60005b838110156147e45781810151838201526020016147cc565b50506000910152565b60006147f7825190565b80845260208401935061480e8185602086016147c9565b601f01601f19169290920192915050565b60208082528101610a9b81846147ed565b60006001600160a01b038216610a3e565b61484a81614830565b8114610acc57600080fd5b8035610a3e81614841565b8061484a565b8035610a3e81614860565b6000806040838503121561488757614887600080fd5b60006148938585614855565b92505060206148a485828601614866565b9150509250929050565b8015156147b5565b60208101610a3e82846148ae565b6000602082840312156148d9576148d9600080fd5b6000611b268484614855565b60ff81166147b5565b60208101610a3e82846148e5565b806147b5565b60208101610a3e82846148fc565b60ff811661484a565b8035610a3e81614910565b60006020828403121561493957614939600080fd5b6000611b268484614919565b60008060006060848603121561495d5761495d600080fd5b60006149698686614855565b935050602061497a86828701614855565b925050604061498b86828701614866565b9150509250925092565b60008083601f8401126149aa576149aa600080fd5b5081356001600160401b038111156149c4576149c4600080fd5b6020830191508360018202830111156149df576149df600080fd5b9250929050565b600080602083850312156149fc576149fc600080fd5b82356001600160401b03811115614a1557614a15600080fd5b614a2185828601614995565b92509250509250929050565b60008083601f840112614a4257614a42600080fd5b5081356001600160401b03811115614a5c57614a5c600080fd5b6020830191508360208202830111156149df576149df600080fd5b60008060208385031215614a8d57614a8d600080fd5b82356001600160401b03811115614aa657614aa6600080fd5b614a2185828601614a2d565b600060208284031215614ac757614ac7600080fd5b6000611b268484614866565b80151561484a565b8035610a3e81614ad3565b60008060408385031215614afc57614afc600080fd5b6000614b088585614855565b92505060206148a485828601614adb565b6147b581614830565b60208101610a3e8284614b19565b63ffffffff81166147b5565b60208101610a3e8284614b30565b60008060008060008060608789031215614b6657614b66600080fd5b86356001600160401b03811115614b7f57614b7f600080fd5b614b8b89828a01614a2d565b965096505060208701356001600160401b03811115614bac57614bac600080fd5b614bb889828a01614a2d565b945094505060408701356001600160401b03811115614bd957614bd9600080fd5b614be589828a01614a2d565b92509250509295509295509295565b6001600160f81b031981166147b5565b6000614c1083836148fc565b505060200190565b6000614c22825190565b80845260209384019383018060005b83811015614c56578151614c458882614c04565b975060208301925050600101614c31565b509495945050505050565b60e08101614c6f828a614bf4565b8181036020830152614c8181896147ed565b90508181036040830152614c9581886147ed565b9050614ca460608301876148fc565b614cb16080830186614b19565b614cbe60a08301856148fc565b81810360c0830152614cd08184614c18565b9998505050505050505050565b65ffffffffffff81166147b5565b60208101610a3e8284614cdd565b60008060008060008060c08789031215614d1557614d15600080fd5b6000614d218989614855565b9650506020614d3289828a01614866565b9550506040614d4389828a01614866565b9450506060614d5489828a01614919565b9350506080614d6589828a01614866565b92505060a0614d7689828a01614866565b9150509295509295509295565b600080600060408486031215614d9b57614d9b600080fd5b6000614da78686614866565b93505060208401356001600160401b03811115614dc657614dc6600080fd5b614dd286828701614995565b92509250509250925092565b60008060408385031215614df457614df4600080fd5b6000614e008585614855565b92505060206148a485828601614855565b63ffffffff811661484a565b8035610a3e81614e11565b60008060408385031215614e3e57614e3e600080fd5b6000614e4a8585614855565b92505060206148a485828601614e1d565b6001600160d01b0381166147b5565b80516040830190614e7b8482614cdd565b5060208201516112296020850182614e5b565b60408101610a3e8284614e6a565b634e487b7160e01b600052602260045260246000fd5b600281046001821680614ec657607f821691505b602082108103614ed857614ed8614e9c565b50919050565b634e487b7160e01b600052603260045260246000fd5b8051610a3e81614ad3565b600060208284031215614f1457614f14600080fd5b6000611b268484614ef4565b60208082528101610a3e8160158152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b602082015260400190565b634e487b7160e01b600052604160045260246000fd5b60408101614f7782856148fc565b610a9b6020830184614cdd565b8051610a3e81614860565b600060208284031215614fa457614fa4600080fd5b6000611b268484614f84565b634e487b7160e01b600052601160045260246000fd5b80820180821115610a3e57610a3e614fb0565b601f19601f83011681018181106001600160401b0382111715614ffe57614ffe614f53565b6040525050565b600061501060405190565b90506116ae8282614fd9565b6001600160801b03811661484a565b8051610a3e8161501c565b6001600160401b03811661484a565b8051610a3e81615036565b600060a0828403121561506557615065600080fd5b61506f60a0615005565b9050600061507d848461502b565b825250602061508e84848301615045565b60208301525060406150a284828501615045565b60408301525060606150b684828501614f84565b60608301525060806150ca84828501615045565b60808301525092915050565b600060a082840312156150eb576150eb600080fd5b6000611b268484615050565b6001600160401b0381166147b5565b60208101610a3e82846150f7565b6060810161512282866148fc565b61512f6020830185614b19565b611b2660408301846148fc565b6060810161514a8286614b19565b61512f60208301856148fc565b6040810161516582856148fc565b610a9b6020830184614b19565b81810381811115610a3e57610a3e614fb0565b8051610a3e81614910565b6000602082840312156151a5576151a5600080fd5b6000611b268484615185565b634e487b7160e01b600052601260045260246000fd5b6000826151d6576151d66151b1565b500490565b604081016151e98285614b19565b610a9b60208301846148fc565b604081016152048285614b19565b610a9b60208301846148e5565b6040810161520482856148e5565b604081016151658285614b19565b6080810161523b8287614b19565b6152486020830186614b19565b61525560408301856148fc565b61526260608301846148ae565b95945050505050565b600060ff8216610a3e565b6147b58161526b565b604081016151e98285615276565b6001600160701b03811661484a565b8051610a3e8161528d565b6000602082840312156152bc576152bc600080fd5b6000611b26848461529c565b6001600160701b0381166147b5565b606081016152e58286614b19565b6152f260208301856148e5565b611b2660408301846152c8565b634e487b7160e01b600052600160045260246000fd5b6000610a3e6147878381565b61532a83615315565b815460001960089490940293841b1916921b91909117905550565b6000610aae818484615321565b81811015610bd057615365600082615345565b600101615352565b601f821115610aae576000818152602090206020601f850104810160208510156153945750805b6119616020601f860104830182615352565b81516001600160401b038111156153bf576153bf614f53565b6153c98254614eb2565b6153d482828561536d565b6020601f83116001811461540857600084156153f05750858201515b600019600886021c1981166002860217865550613645565b600085815260208120601f198616915b828110156154385788850151825560209485019460019092019101615418565b868310156154545784890151600019601f89166008021c191682555b600160028802018855505050505050505050565b634e487b7160e01b600052602160045260246000fd5b60a0810161548c82886148fc565b61549960208301876148fc565b6154a660408301866148fc565b6154b360608301856148fc565b61429c6080830184614b19565b608081016154ce82876148fc565b6154db60208301866148e5565b6154e860408301856148fc565b61526260608301846148fc565b604081016151e982856148fc565b600061550d825190565b61551b8185602086016147c9565b9290920192915050565b6000610a9b8284615503565b6001600160d01b03918216919081169082820390811115610a3e57610a3e614fb0565b6001600160d01b03918216919081169082820190811115610a3e57610a3e614fb056fee8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d0052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300a2646970667358221220d72ec53a26ffe04ff3f3f62b720717fb053fe1e61e3336285511e759de4bd5ed64736f6c63430008180033","optimization_enabled":false,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":true,"cse":true,"deduplicate":true,"inliner":true,"jumpdestRemover":true,"orderLiterals":true,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false},"runs":200},"remappings":[]},"optimization_runs":null,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0x73FE14fF5A25e4363a72828cccD8444f0748FDE7/","decoded_constructor_args":[["1756728000",{"internalType":"uint256","name":"_tradingStartTimestamp","type":"uint256"}],["0x4f61A99e42e21eA3c3EaF9B1b30Fb80A7900d3ce",{"internalType":"address","name":"_registry","type":"address"}],["0x74B4f6A2E579D730aAcb9dD23cfbbAEb95029583",{"internalType":"address","name":"_vester","type":"address"}],["0x196feE96efeAAd585483A6d950e70286B6851923",{"internalType":"address","name":"_wlfiStaking","type":"address"}],["10000",{"internalType":"uint32","name":"_multiplierBps","type":"uint32"}]],"compiler_version":"0.8.24+commit.e11b9ed9","is_verified_via_verifier_alliance":false,"verified_at":"2026-09-30T15:26:08.666033Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6101206040523480156200001257600080fd5b5060405162005a2738038062005a27833981016040819052620000359162000203565b84848482828262000045620000e5565b6080929092526001600160a01b0390811660a05290811660c05285161592508291506200007c905057506001600160a01b0382163b155b156200009b576040516307b18df360e31b815260040160405180910390fd5b8063ffffffff16600003620000c357604051631f49f9c160e01b815260040160405180910390fd5b6001600160a01b0390911660e05263ffffffff1661010052506200029d915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620001365760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146200019b5780546001600160401b0319166001600160401b0390811782556040517fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d291620001929162000287565b60405180910390a15b50565b805b81146200019b57600080fd5b8051620001b9816200019e565b92915050565b60006001600160a01b038216620001b9565b620001a081620001bf565b8051620001b981620001d1565b63ffffffff8116620001a0565b8051620001b981620001e9565b600080600080600060a08688031215620002205762000220600080fd5b60006200022e8888620001ac565b95505060206200024188828901620001dc565b94505060406200025488828901620001dc565b93505060606200026788828901620001dc565b92505060806200027a88828901620001f6565b9150509295509295909350565b6001600160401b038216815260208101620001b9565b60805160a05160c05160e0516101005161562d620003fa6000396000613226015260008181610584015281816114b80152611565015260008181610840015281816112d8015281816114290152818161163601528181611a1001528181611aa601528181611b6501528181612130015281816122f901528181612384015281816124490152818161254d01528181612c5d0152818161310b015281816131370152818161317c015281816131ed015281816133d9015261340b0152600081816103fb01528181610cb901528181610d4d01528181611fd901528181612083015281816121e2015281816124c7015281816125cb015281816128a30152818161296201528181612a2e01528181612ac401528181612b4901528181612bdf01528181612f7601528181612ff601528181613073015281816134d201526135a4015260008181610518015281816107a401526133b0015261562d6000f3fe608060405234801561001057600080fd5b50600436106103f15760003560e01c80637df9a67411610215578063c455d4f611610125578063e1dfc884116100b8578063f13253bb11610087578063f13253bb1461091f578063f2fde38b14610927578063f36e05151461093a578063fbe2518f14610966578063fe575a871461096e57600080fd5b8063e1dfc884146108d1578063e30c3978146108e4578063e5195157146108ec578063f1127ed8146108ff57600080fd5b8063ce5a7e4e116100f4578063ce5a7e4e14610890578063d4593872146108a3578063dd1d1d9e146108ab578063dd62ed3e146108be57600080fd5b8063c455d4f61461083b578063c4d66de814610862578063c771909c14610875578063c7dac7041461087d57600080fd5b806395d89b41116101a8578063a9059cbb11610177578063a9059cbb146107e1578063b6274f3d146107f4578063bb4d443614610807578063bfc9c3591461081a578063c3cda5201461082d57600080fd5b806395d89b411461079757806395d9538d1461079f578063967f1cc6146107c65780639ab24eb0146107ce57600080fd5b80638da5cb5b116101e45780638da5cb5b146107545780638e539e8c1461075c57806391ddadf41461076f57806394d4827f1461078457600080fd5b80637df9a674146107005780637ecebe001461071357806384b0196e146107265780638682db371461074157600080fd5b80633a46b1a8116103105780635c19a95c116102a357806370a082311161027257806370a08231146106b7578063715018a6146106ca57806379ba5097146106d257806379cc6790146106da5780637adf1239146106ed57600080fd5b80635c19a95c146106595780635c975abb1461066c5780636fc9028e146106845780636fcfff451461069757600080fd5b806356f31c5d116102df57806356f31c5d146105e7578063587cde1e146105fa5780635a2cba271461061a5780635aa42d121461064657600080fd5b80633a46b1a8146105a657806342966c68146105b95780634bf5d7e9146105cc57806356c531b9146105d457600080fd5b806318160ddd116103885780632ad36687116103575780632ad3668714610552578063313ce567146105655780633254862e1461056c578063355e24bb1461057f57600080fd5b806318160ddd146104dc57806323b872dd14610503578063241f1c9914610516578063252f38671461053f57600080fd5b80630f861ca3116103c45780630f861ca314610494578063144220ea1461049e578063152439db146104b3578063172fe9e2146104c957600080fd5b806306433b1b146103f657806306fdde0314610433578063095ea7b3146104485780630c68ba2114610468575b600080fd5b61041d7f000000000000000000000000000000000000000000000000000000000000000081565b60405161042a91906147bb565b60405180910390f35b61043b610981565b60405161042a919061481f565b61045b610456366004614871565b610a2a565b60405161042a91906148b6565b61045b6104763660046148c4565b6001600160a01b031660009081526001602052604090205460ff1690565b61049c610a44565b005b6104a6602d81565b60405161042a91906148ee565b6104bc60005481565b60405161042a9190614902565b61045b6104d7366004614924565b610a5e565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02546104bc565b61045b610511366004614945565b610a7c565b7f000000000000000000000000000000000000000000000000000000000000000042101561045b565b61049c61054d3660046149e6565b610aa2565b61049c6105603660046148c4565b610ab3565b60126104a6565b61049c61057a366004614a77565b610acf565b61041d7f000000000000000000000000000000000000000000000000000000000000000081565b6104bc6105b4366004614871565b610b21565b61049c6105c7366004614ab2565b610b3c565b61043b610b46565b61049c6105e2366004614ae6565b610bbe565b61049c6105f5366004614ab2565b610bd4565b61060d6106083660046148c4565b610c49565b60405161042a9190614b22565b61045b6106283660046148c4565b6001600160a01b031660009081526002602052604090205460ff1690565b61049c610654366004614ae6565b610c74565b61049c6106673660046148c4565b610c86565b6000805160206155d88339815191525460ff1661045b565b61045b6106923660046148c4565b610c9f565b6106aa6106a53660046148c4565b610dc3565b60405161042a9190614b3c565b6104bc6106c53660046148c4565b610dce565b61049c610e01565b61049c610e22565b61049c6106e8366004614871565b610e67565b61049c6106fb366004614b4a565b610e7c565b61049c61070e366004614945565b610f45565b6104bc6107213660046148c4565b610f58565b61072e610f81565b60405161042a9796959493929190614c61565b61049c61074f366004614ae6565b611005565b61060d611094565b6104bc61076a366004614ab2565b6110c9565b610777611138565b60405161042a9190614ceb565b61049c610792366004614945565b611147565b61043b61122f565b6104bc7f000000000000000000000000000000000000000000000000000000000000000081565b61049c61126e565b6104bc6107dc3660046148c4565b611286565b61045b6107ef366004614871565b6113a6565b61049c610802366004614ae6565b6113b4565b6104bc6108153660046148c4565b6113c6565b6104bc6108283660046148c4565b61160d565b61049c610667366004614cf9565b61041d7f000000000000000000000000000000000000000000000000000000000000000081565b61049c6108703660046148c4565b6116b3565b61060d6117c9565b61049c61088b366004614ae6565b6117e5565b6104bc61089e366004614ab2565b611841565b61049c611857565b61049c6108b9366004614d83565b61185f565b6104bc6108cc366004614dde565b611968565b61049c6108df366004614ae6565b6119b2565b61060d6119ba565b6104bc6108fa3660046149e6565b6119e3565b61091261090d366004614e28565b611b2e565b60405161042a9190614e8e565b6104bc611b4c565b61049c6109353660046148c4565b611be5565b61045b6109483660046148c4565b6001600160a01b031660009081526003602052604090205460ff1690565b6104a6602f81565b61045b61097c3660046148c4565b611c6a565b606060006000805160206155988339815191525b90508060030180546109a690614eb2565b80601f01602080910402602001604051908101604052809291908181526020018280546109d290614eb2565b8015610a1f5780601f106109f457610100808354040283529160200191610a1f565b820191906000526020600020905b815481529060010190602001808311610a0257829003601f168201915b505050505091505090565b600033610a38818585611c96565b60019150505b92915050565b610a4c611ca3565b610a54611cd5565b610a5c611d05565b565b600060028260ff1610158015610a3e575050601460ff909116111590565b600033610a8a858285611d54565b610a95858585611da1565b60019150505b9392505050565b33610aae818484611e00565b505050565b610abb611ca3565b610acc610ac6611ebd565b82611f1d565b50565b610ad7611ca3565b610adf611f91565b60005b81811015610aae57610b19838383818110610aff57610aff614ede565b9050602002016020810190610b1491906148c4565b611fc2565b600101610ae2565b600060405163d623472560e01b815260040160405180910390fd5b610acc338261267e565b6060610b506126b4565b65ffffffffffff16610b60611138565b65ffffffffffff1614610b86576040516301bfc1c560e61b815260040160405180910390fd5b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b610bc6611ca3565b610bd082826126bf565b5050565b610bdc611ca3565b6b1027e72f1f12813088000000811115610c095760405163cec0812160e01b815260040160405180910390fd5b60008190556040517fe891886eac9e583940fb0844098689693a4d105206ec1f789d119b4314383b9590610c3e908390614902565b60405180910390a150565b6001600160a01b03908116600090815260008051602061557883398151915260205260409020541690565b610c7c612724565b610bd08282612756565b604051638510efe160e01b815260040160405180910390fd5b60405163d68b948d60e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d68b948d90610cee908590600401614b22565b602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190614eff565b1580610a3e57506040516325b6123360e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634b6c246690610d82908590600401614b22565b602060405180830381865afa158015610d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190614eff565b6000610a3e826127c9565b6000806000805160206155988339815191525b6001600160a01b0390931660009081526020939093525050604090205490565b610e09611ca3565b60405163d623472560e01b815260040160405180910390fd5b3380610e2c6119ba565b6001600160a01b031614610e5e578060405163118cdaa760e01b8152600401610e559190614b22565b60405180910390fd5b610acc8161281a565b610e72823383611d54565b610bd0828261267e565b610e84611ca3565b841580610e915750848314155b80610e9c5750828114155b15610eba57604051630e52390960e41b815260040160405180910390fd5b60005b85811015610f3c57610f34878783818110610eda57610eda614ede565b9050602002016020810190610eef91906148c4565b868684818110610f0157610f01614ede565b9050602002016020810190610f1691906148c4565b858585818110610f2857610f28614ede565b90506020020135612852565b600101610ebd565b50505050505050565b610f4d611ca3565b610aae838383612852565b6000807f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00610de1565b600060608082808083816000805160206155b88339815191528054909150158015610fae57506001810154155b610fca5760405162461bcd60e51b8152600401610e5590614f20565b610fd2612d1f565b610fda612d5e565b60408051600080825260208201909252600f60f81b9c939b5091995046985030975095509350915050565b61100d611ca3565b6001600160a01b03821661103457604051630da30f6560e31b815260040160405180910390fd5b6001600160a01b03821660008181526001602052604090819020805460ff1916841515179055517fca139a0ba60fe6426dd1d713a05ec0c645224f72d7a9912d64163974672dd410906110889084906148b6565b60405180910390a25050565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005b546001600160a01b031692915050565b6000600080516020615578833981519152816110e3611138565b90508065ffffffffffff168410611111578381604051637669fc0f60e11b8152600401610e55929190614f69565b61112761111d85612d76565b6002840190612da8565b6001600160d01b0316949350505050565b60006111426126b4565b905090565b61114f611ca3565b6001600160a01b03831661117657604051630da30f6560e31b815260040160405180910390fd5b8060000361119757604051632a9ffab760e21b815260040160405180910390fd5b6040516370a0823160e01b81526000906001600160a01b038416906370a08231906111c6903090600401614b22565b602060405180830381865afa1580156111e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112079190614f8f565b905080821115611215578091505b6112296001600160a01b0384168584612e5e565b50505050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace048054606091600080516020615598833981519152916109a690614eb2565b611276611ca3565b61127e611f91565b610a5c612eb6565b6001600160a01b03811660009081526003602052604081205460ff16806112b157506112b182611c6a565b156112be57506000919050565b60405163282de9ed60e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063505bd3da9061130d908690600401614b22565b602060405180830381865afa15801561132a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134e9190614f8f565b61135784612eff565b6113619190614fc6565b9050600061136e84610c49565b6001600160a01b0316036113925761138583610dce565b61138f9082614fc6565b90505b600054811115610a3e575050600054919050565b600033610a38818585611da1565b6113bc611ca3565b610bd08282612f5f565b60006001600160a01b03821615806113f657506001600160a01b03821660009081526003602052604090205460ff165b80611405575061140582611c6a565b1561141257506000919050565b60405163282de9ed60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063505bd3da9061145e908590600401614b22565b602060405180830381865afa15801561147b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149f9190614f8f565b6114a883610dce565b6114b29190614fc6565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663300e1db8846040518263ffffffff1660e01b81526004016115029190614b22565b602060405180830381865afa15801561151f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115439190614f8f565b905080156116015760405163f4dadc6160e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f4dadc619061159a908590600401614902565b60a060405180830381865afa1580156115b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115db91906150d6565b90506115f381600001516001600160801b031661321e565b6115fd9084614fc6565b9250505b610a9b82600054613253565b6000611617611f91565b61161f611ca3565b604051632e6639a560e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b998e6949061166b908590600401614b22565b6020604051808303816000875af115801561168a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190614f8f565b919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff16806116fc575080546001600160401b03808416911610155b1561171a5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b178155611765611746610981565b604051806040016040528060018152602001601960f91b815250613269565b600061176f611ebd565b905061177b8185611f1d565b50805468ff0000000000000000191681556040517fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2906117bc908490615106565b60405180910390a1505050565b60006117d3611ebd565b600101546001600160a01b0316919050565b6117ed611ca3565b6001600160a01b03821660008181526002602052604090819020805460ff1916841515179055517fe4b88447f604c5e795f270c2758f4822062b56a3c2fc8b75394b077ba1dbf8ff906110889084906148b6565b6000610a3e61184f8361321e565b600054613253565b611276612724565b611867611f91565b334284101561188957604051631ab7da6b60e01b815260040160405180910390fd5b60006118de7f33a518e58b94b9604db5b08c90c70e148297bb153fdbe2be45395ac5b6e4640b83876040516020016118c393929190615114565b6040516020818303038152906040528051906020012061327b565b90506119208185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132a892505050565b6001600160a01b03166119316117c9565b6001600160a01b03161461195857604051638baa579f60e01b815260040160405180910390fd5b61196182611fc2565b5050505050565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b610c7c611ca3565b6000807f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c006110b9565b60006119ed611f91565b336119f9818585611e00565b60405163402914f560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063402914f590611a45908490600401614b22565b602060405180830381865afa158015611a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a869190614f8f565b600003611a97576000915050610a3e565b604051632e6639a560e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b998e69490611ae3903390600401614b22565b6020604051808303816000875af1158015611b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b269190614f8f565b949350505050565b6040805180820190915260008082526020820152610a9b83836132d2565b6000611b56611f91565b604051632e6639a560e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b998e69490611ba2903390600401614b22565b6020604051808303816000875af1158015611bc1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111429190614f8f565b611bed611ca3565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080546001600160a01b0319166001600160a01b0383169081178255611c31611094565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b6000611c74611ebd565b6001600160a01b03909216600090815260209290925250604090205460ff1690565b610aae8383836001613335565b33611cac611094565b6001600160a01b031614610a5c573360405163118cdaa760e01b8152600401610e559190614b22565b6000805160206155d88339815191525460ff16610a5c57604051638dfc202b60e01b815260040160405180910390fd5b611d0d611cd5565b6000805160206155d8833981519152805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051610c3e9190614b22565b6000611d608484611968565b905060001981146112295781811015611d9257828183604051637dc7a0d960e11b8152600401610e559392919061513c565b61122984848484036000613335565b6001600160a01b038316611dcb576000604051634b637e8f60e11b8152600401610e559190614b22565b6001600160a01b038216611df557600060405163ec442f0560e01b8152600401610e559190614b22565b610aae838383613367565b6000611e387f214b6837b0cb36c3dfa2494ae052b630f55f351d9e069e1c5920491aa344a514856040516020016118c3929190615157565b9050611e7a8184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132a892505050565b6001600160a01b0316611e8b6117c9565b6001600160a01b031614611eb257604051638baa579f60e01b815260040160405180910390fd5b611229846000612f5f565b60008060ff19611eee60017f5d14c3535674e7f5942e30e2a55bfc241c205a216ca5bfc40c567afac5d67ad3615172565b604051602001611efe9190614902565b60408051601f1981840301815291905280516020909101201692915050565b6001600160a01b038116611f445760405163371685cf60e11b815260040160405180910390fd5b6001820180546001600160a01b0319166001600160a01b0383169081179091556040517fdc26eaa07c3e782e27ef385f6a52197f10505eed55db43e69a3d522714d0875a90600090a25050565b6000805160206155d88339815191525460ff1615610a5c5760405163d93c066560e01b815260040160405180910390fd5b60405163d68b948d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d68b948d9061200e908490600401614b22565b602060405180830381865afa15801561202b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204f9190614eff565b61206c57604051630da30f6560e31b815260040160405180910390fd5b604051630eb2335d60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633ac8cd74906120b8908490600401614b22565b602060405180830381865afa1580156120d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f99190614eff565b15612119578060405163583c441960e11b8152600401610e559190614b22565b604051630b81b86360e41b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b81b863090612165908490600401614b22565b602060405180830381865afa158015612182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a69190614f8f565b6000036121c8578060405163482aa09560e01b8152600401610e559190614b22565b604051635d0ecba760e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ba1d974e90612217908590600401614b22565b602060405180830381865afa158015612234573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122589190615190565b905060ff8116602d148061226f575060ff8116602f145b1561228c576040516217bf7f60e81b815260040160405180910390fd5b600060001960ff8316016122a25750602d6122d3565b6122ab82610a5e565b156122b85750602f6122d3565b8160405163643a2f0760e11b8152600401610e5591906148ee565b602e1960ff82160161253657604051630b81b86360e41b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b81b86309061232e908790600401614b22565b602060405180830381865afa15801561234b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236f9190614f8f565b9050600061237e600a836151c7565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c884ef83876040518263ffffffff1660e01b81526004016123ce9190614b22565b602060405180830381865afa1580156123eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240f9190614f8f565b90508015612432578560405163559073f160e11b8152600401610e559190614b22565b60405163d89e836f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d89e836f9061248090899086906004016151db565b600060405180830381600087803b15801561249a57600080fd5b505af11580156124ae573d6000803e3d6000fd5b505060405163d89e836f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063d89e836f915061250090899086906004016151db565b600060405180830381600087803b15801561251a57600080fd5b505af115801561252e573d6000803e3d6000fd5b505050505050505b604051631221980760e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632443300e9061258490869085906004016151f6565b600060405180830381600087803b15801561259e57600080fd5b505af11580156125b2573d6000803e3d6000fd5b5050604051631221980760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250632443300e915061260490869085906004016151f6565b600060405180830381600087803b15801561261e57600080fd5b505af1158015612632573d6000803e3d6000fd5b50505050826001600160a01b03167ffc5a3510b90b1cebfceb2e53f8b658f2f4b4743ac89a379aa32f6250ebae35458383604051612671929190615211565b60405180910390a2505050565b6001600160a01b0382166126a8576000604051634b637e8f60e11b8152600401610e559190614b22565b610bd082600083613367565b600061114243612d76565b80156126d0576126d082600061364d565b6001600160a01b03821660008181526003602052604090819020805460ff1916841515179055517f662fe17a45a2827abeda36082dde83f496af4ace698c1db04e760bc78bd8be03906110889084906148b6565b3360008181526001602052604090205460ff16610acc5780604051635a968dab60e01b8152600401610e559190614b22565b80156127675761276782600061364d565b80612770611ebd565b6001600160a01b0384166000818152602092909252604091829020805460ff191693151593909317909255517f5019745a56bcdd97726f5b35a7bfcb97ffa4e40b51bc2f6f764c6671e1bef6d4906110889084906148b6565b6001600160a01b03811660009081527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d01602052604081205460008051602061557883398151915290610a9b906136b9565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080546001600160a01b0319168155610bd0826136e5565b600061285c611ebd565b6001600160a01b03851660009081526020829052604090205490915060ff16801561288c5761288c856000612756565b604051630eb2335d60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633ac8cd74906128d8908890600401614b22565b602060405180830381865afa1580156128f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129199190614eff565b801561292d57508261292a86610dce565b14155b1561294b57604051632dfd9c3960e01b815260040160405180910390fd5b60405163d68b948d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d68b948d90612997908790600401614b22565b602060405180830381865afa1580156129b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129d89190614eff565b156129fa57848460405163314b500b60e21b8152600401610e5592919061521f565b8215612a1457612a0a858461267e565b612a148484613756565b604051630eb2335d60e21b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633ac8cd7490612a63908990600401614b22565b602060405180830381865afa158015612a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa49190614eff565b15612b3257506040516302612aeb60e21b81526001906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630984abac90612afb908990899060040161521f565b600060405180830381600087803b158015612b1557600080fd5b505af1158015612b29573d6000803e3d6000fd5b50505050612cc9565b6040516325b6123360e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634b6c246690612b7e908990600401614b22565b602060405180830381865afa158015612b9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbf9190614eff565b15612cc957506040516302612aeb60e21b81526001906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630984abac90612c16908990899060040161521f565b600060405180830381600087803b158015612c3057600080fd5b505af1158015612c44573d6000803e3d6000fd5b50506040516302612aeb60e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250630984abac9150612c96908990899060040161521f565b600060405180830381600087803b158015612cb057600080fd5b505af1158015612cc4573d6000803e3d6000fd5b505050505b8115612cda57612cda866001612756565b7f7010a46c57b41359be039fda242f641df5204a59c81af3f06adbf8317100400686868684604051612d0f949392919061522d565b60405180910390a1505050505050565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060916000805160206155b8833981519152916109a690614eb2565b606060006000805160206155b8833981519152610995565b600065ffffffffffff821115612da4576030826040516306dfcc6560e41b8152600401610e5592919061527f565b5090565b815460009081816005811115612e07576000612dc38461378c565b612dcd9085615172565b60008881526020902090915081015465ffffffffffff9081169087161015612df757809150612e05565b612e02816001614fc6565b92505b505b6000612e1587878585613874565b90508015612e5057612e3a87612e2c600184615172565b600091825260209091200190565b54600160301b90046001600160d01b0316612e53565b60005b979650505050505050565b610aae83846001600160a01b031663a9059cbb8585604051602401612e849291906151db565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506138d6565b612ebe611f91565b6000805160206155d8833981519152805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833611d47565b6001600160a01b03811660009081527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d016020526040812060008051602061557883398151915290612f4f90613930565b6001600160d01b03169392505050565b604051634f1908cd60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634f1908cd90612fab908590600401614b22565b600060405180830381600087803b158015612fc557600080fd5b505af1158015612fd9573d6000803e3d6000fd5b5050604051635d0ecba760e11b8152600092506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063ba1d974e9061302c908690600401614b22565b602060405180830381865afa158015613049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061306d9190615190565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632402f27f856040518263ffffffff1660e01b81526004016130bd9190614b22565b602060405180830381865afa1580156130da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130fe91906152a7565b90508261122957613131847f00000000000000000000000000000000000000000000000000000000000000006000611c96565b613165847f0000000000000000000000000000000000000000000000000000000000000000836001600160701b0316611c96565b60405163b5f3b57d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b5f3b57d906131b5908790869086906004016152d7565b600060405180830381600087803b1580156131cf57600080fd5b505af11580156131e3573d6000803e3d6000fd5b50505050613211847f0000000000000000000000000000000000000000000000000000000000000000611968565b15611229576112296152ff565b6000610a3e827f000000000000000000000000000000000000000000000000000000000000000063ffffffff16612710613969565b60008183106132625781610a9b565b5090919050565b613271613a2d565b610bd08282613a76565b6000610a3e613288613ad7565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000806132b88686613ae1565b9250925092506132c88282613b2e565b5090949350505050565b604080518082018252600080825260208083018290526001600160a01b03861682527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d0190529190912060008051602061557883398151915290611b269084613be5565b3361333f81613c55565b8461334981613c55565b8461335381613c55565b61335b611f91565b610f3c87878787613cb1565b3361337181613c55565b8361337b81613c55565b8361338581613c55565b306001600160a01b038616036133ae57604051630da30f6560e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000004210156134bb57337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614801561343f57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b80613462575061344d611094565b6001600160a01b0316336001600160a01b0316145b1561347757613472868686613d96565b613645565b6001600160a01b03861660009081526002602052604090205460ff166134b05760405163af423a6f60e01b815260040160405180910390fd5b613472868686613d96565b604051630eb2335d60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633ac8cd7490613507908990600401614b22565b602060405180830381865afa158015613524573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135489190614eff565b801561356d5750613557611094565b6001600160a01b0316336001600160a01b031614155b1561358d578560405163583c441960e11b8152600401610e559190614b22565b604051630eb2335d60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633ac8cd74906135d9908890600401614b22565b602060405180830381865afa1580156135f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061361a9190614eff565b1561363a578460405163583c441960e11b8152600401610e559190614b22565b613645868686613d96565b505050505050565b3361365781613c55565b8261366181613c55565b8261366b81613c55565b613673611f91565b6001600160a01b03851660009081526003602052604090205460ff16156136af578460405163064a023360e51b8152600401610e559190614b22565b6119618585613da9565b600063ffffffff821115612da4576020826040516306dfcc6560e41b8152600401610e5592919061527f565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001600160a01b03821661378057600060405163ec442f0560e01b8152600401610e559190614b22565b610bd060008383613367565b60008160000361379e57506000919050565b600060016137ab84613e33565b901c6001901b905060018184816137c4576137c46151b1565b048201901c905060018184816137dc576137dc6151b1565b048201901c905060018184816137f4576137f46151b1565b048201901c9050600181848161380c5761380c6151b1565b048201901c90506001818481613824576138246151b1565b048201901c9050600181848161383c5761383c6151b1565b048201901c90506001818481613854576138546151b1565b048201901c9050610a9b8182858161386e5761386e6151b1565b04613253565b60005b818310156138ce57600061388b8484613ec7565b60008781526020902090915065ffffffffffff86169082015465ffffffffffff1611156138ba578092506138c8565b6138c5816001614fc6565b93505b50613877565b509392505050565b60006138eb6001600160a01b03841683613ee2565b9050805160001415801561391057508080602001905181019061390e9190614eff565b155b15610aae5782604051635274afe760e01b8152600401610e559190614b22565b805460009080156139605761394a83612e2c600184615172565b54600160301b90046001600160d01b0316610a9b565b60009392505050565b60008383028160001985870982811083820303915050806000036139a057838281613996576139966151b1565b0492505050610a9b565b8084116139c05760405163227bc15360e01b815260040160405180910390fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610a5c57604051631afcd79f60e31b815260040160405180910390fd5b613a7e613a2d565b6000805160206155b88339815191527fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102613ab884826153a6565b5060038101613ac783826153a6565b5060008082556001909101555050565b6000611142613ef0565b60008060008351604103613b1b5760208401516040850151606086015160001a613b0d88828585613f54565b955095509550505050613b27565b50508151600091506002905b9250925092565b6000826003811115613b4257613b42615468565b03613b4b575050565b6001826003811115613b5f57613b5f615468565b03613b7d5760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115613b9157613b91615468565b03613bb15760405163fce698f760e01b8152610e55908290600401614902565b6003826003811115613bc557613bc5615468565b03610bd057806040516335e2f38360e21b8152600401610e559190614902565b6040805180820190915260008082526020820152826000018263ffffffff1681548110613c1457613c14614ede565b60009182526020918290206040805180820190915291015465ffffffffffff81168252600160301b90046001600160d01b0316918101919091529392505050565b6001600160a01b03811615801590613c8e5750613c70611ebd565b6001600160a01b0382166000908152602091909152604090205460ff165b15610acc57806040516001620b633d60e31b03198152600401610e559190614b22565b6000805160206155988339815191526001600160a01b038516613cea57600060405163e602df0560e01b8152600401610e559190614b22565b6001600160a01b038416613d14576000604051634a1406b160e11b8152600401610e559190614b22565b6001600160a01b0380861660009081526001830160209081526040808320938816835292905220839055811561196157836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051613d879190614902565b60405180910390a35050505050565b613d9e611f91565b610aae838383614016565b6000805160206155788339815191526000613dc384610c49565b6001600160a01b0385811660008181526020869052604080822080546001600160a01b031916898616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46112298184613e2e87614096565b6140a1565b600080608083901c15613e4857608092831c92015b604083901c15613e5a57604092831c92015b602083901c15613e6c57602092831c92015b601083901c15613e7e57601092831c92015b600883901c15613e9057600892831c92015b600483901c15613ea257600492831c92015b600283901c15613eb457600292831c92015b600183901c15610a3e5760010192915050565b6000613ed660028484186151c7565b610a9b90848416614fc6565b6060610a9b83836000614209565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f613f1b6142a6565b613f23614310565b4630604051602001613f3995949392919061547e565b60405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115613f8f575060009150600390508261400c565b600060018888888860405160008152602001604052604051613fb494939291906154c0565b6020604051602081039080840390855afa158015613fd6573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166140025750600092506001915082905061400c565b9250600091508190505b9450945094915050565b614021838383614354565b6001600160a01b03831661408b5760006140597f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025490565b90506001600160d01b0380821115614088578181604051630e58ae9360e11b8152600401610e559291906154f5565b50505b610aae83838361447d565b6000610a3e82610dce565b6000805160206155788339815191526001600160a01b03848116908416148015906140cc5750600082115b15611229576001600160a01b0384161561416d576001600160a01b038416600090815260018201602052604081208190614111906144ef61410c876144fb565b61452a565b6001600160d01b031691506001600160d01b03169150856001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516141629291906154f5565b60405180910390a250505b6001600160a01b03831615611229576001600160a01b0383166000908152600182016020526040812081906141a89061456361410c876144fb565b6001600160d01b031691506001600160d01b03169150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516141f99291906154f5565b60405180910390a2505050505050565b60608147101561422e573060405163cd78605960e01b8152600401610e559190614b22565b600080856001600160a01b0316848660405161424a9190615525565b60006040518083038185875af1925050503d8060008114614287576040519150601f19603f3d011682016040523d82523d6000602084013e61428c565b606091505b509150915061429c86838361456f565b9695505050505050565b60006000805160206155b8833981519152816142c0612d1f565b8051909150156142d857805160209091012092915050565b815480156142e7579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b60006000805160206155b88339815191528161432a612d5e565b80519091501561434257805160209091012092915050565b600182015480156142e7579392505050565b6000805160206155988339815191526001600160a01b03841661439057818160020160008282546143859190614fc6565b909155506143ef9050565b6001600160a01b038416600090815260208290526040902054828110156143d05784818460405163391434e360e21b8152600401610e559392919061513c565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b03831661440d57600281018054839003905561442c565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161446f9190614902565b60405180910390a350505050565b6000805160206155788339815191526001600160a01b0384166144b0576144ad8160020161456361410c856144fb565b50505b6001600160a01b0383166144d4576144d1816002016144ef61410c856144fb565b50505b6112296144e085610c49565b6144e985610c49565b846140a1565b6000610a9b8284615531565b60006001600160d01b03821115612da45760d0826040516306dfcc6560e41b8152600401610e5592919061527f565b600080614556614538611138565b61454e61454488613930565b868863ffffffff16565b8791906145c2565b915091505b935093915050565b6000610a9b8284615554565b6060826145845761457f826145d0565b610a9b565b815115801561459b57506001600160a01b0384163b155b156145bb5783604051639996b31560e01b8152600401610e559190614b22565b5080610a9b565b6000806145568585856145f9565b8051156145e05780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b82546000908190801561471857600061461787612e2c600185615172565b60408051808201909152905465ffffffffffff808216808452600160301b9092046001600160d01b03166020840152919250908716101561466b57604051632520601d60e01b815260040160405180910390fd5b805165ffffffffffff8088169116036146b7578461468e88612e2c600186615172565b80546001600160d01b0392909216600160301b0265ffffffffffff909216919091179055614708565b6040805180820190915265ffffffffffff80881682526001600160d01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160301b029216919091179101555b60200151925083915061455b9050565b50506040805180820190915265ffffffffffff80851682526001600160d01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160301b02919093161792019190915590508161455b565b6000610a3e6001600160a01b03831661478a565b90565b6001600160a01b031690565b6000610a3e82614773565b6000610a3e82614796565b6147b5816147a1565b82525050565b60208101610a3e82846147ac565b60005b838110156147e45781810151838201526020016147cc565b50506000910152565b60006147f7825190565b80845260208401935061480e8185602086016147c9565b601f01601f19169290920192915050565b60208082528101610a9b81846147ed565b60006001600160a01b038216610a3e565b61484a81614830565b8114610acc57600080fd5b8035610a3e81614841565b8061484a565b8035610a3e81614860565b6000806040838503121561488757614887600080fd5b60006148938585614855565b92505060206148a485828601614866565b9150509250929050565b8015156147b5565b60208101610a3e82846148ae565b6000602082840312156148d9576148d9600080fd5b6000611b268484614855565b60ff81166147b5565b60208101610a3e82846148e5565b806147b5565b60208101610a3e82846148fc565b60ff811661484a565b8035610a3e81614910565b60006020828403121561493957614939600080fd5b6000611b268484614919565b60008060006060848603121561495d5761495d600080fd5b60006149698686614855565b935050602061497a86828701614855565b925050604061498b86828701614866565b9150509250925092565b60008083601f8401126149aa576149aa600080fd5b5081356001600160401b038111156149c4576149c4600080fd5b6020830191508360018202830111156149df576149df600080fd5b9250929050565b600080602083850312156149fc576149fc600080fd5b82356001600160401b03811115614a1557614a15600080fd5b614a2185828601614995565b92509250509250929050565b60008083601f840112614a4257614a42600080fd5b5081356001600160401b03811115614a5c57614a5c600080fd5b6020830191508360208202830111156149df576149df600080fd5b60008060208385031215614a8d57614a8d600080fd5b82356001600160401b03811115614aa657614aa6600080fd5b614a2185828601614a2d565b600060208284031215614ac757614ac7600080fd5b6000611b268484614866565b80151561484a565b8035610a3e81614ad3565b60008060408385031215614afc57614afc600080fd5b6000614b088585614855565b92505060206148a485828601614adb565b6147b581614830565b60208101610a3e8284614b19565b63ffffffff81166147b5565b60208101610a3e8284614b30565b60008060008060008060608789031215614b6657614b66600080fd5b86356001600160401b03811115614b7f57614b7f600080fd5b614b8b89828a01614a2d565b965096505060208701356001600160401b03811115614bac57614bac600080fd5b614bb889828a01614a2d565b945094505060408701356001600160401b03811115614bd957614bd9600080fd5b614be589828a01614a2d565b92509250509295509295509295565b6001600160f81b031981166147b5565b6000614c1083836148fc565b505060200190565b6000614c22825190565b80845260209384019383018060005b83811015614c56578151614c458882614c04565b975060208301925050600101614c31565b509495945050505050565b60e08101614c6f828a614bf4565b8181036020830152614c8181896147ed565b90508181036040830152614c9581886147ed565b9050614ca460608301876148fc565b614cb16080830186614b19565b614cbe60a08301856148fc565b81810360c0830152614cd08184614c18565b9998505050505050505050565b65ffffffffffff81166147b5565b60208101610a3e8284614cdd565b60008060008060008060c08789031215614d1557614d15600080fd5b6000614d218989614855565b9650506020614d3289828a01614866565b9550506040614d4389828a01614866565b9450506060614d5489828a01614919565b9350506080614d6589828a01614866565b92505060a0614d7689828a01614866565b9150509295509295509295565b600080600060408486031215614d9b57614d9b600080fd5b6000614da78686614866565b93505060208401356001600160401b03811115614dc657614dc6600080fd5b614dd286828701614995565b92509250509250925092565b60008060408385031215614df457614df4600080fd5b6000614e008585614855565b92505060206148a485828601614855565b63ffffffff811661484a565b8035610a3e81614e11565b60008060408385031215614e3e57614e3e600080fd5b6000614e4a8585614855565b92505060206148a485828601614e1d565b6001600160d01b0381166147b5565b80516040830190614e7b8482614cdd565b5060208201516112296020850182614e5b565b60408101610a3e8284614e6a565b634e487b7160e01b600052602260045260246000fd5b600281046001821680614ec657607f821691505b602082108103614ed857614ed8614e9c565b50919050565b634e487b7160e01b600052603260045260246000fd5b8051610a3e81614ad3565b600060208284031215614f1457614f14600080fd5b6000611b268484614ef4565b60208082528101610a3e8160158152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b602082015260400190565b634e487b7160e01b600052604160045260246000fd5b60408101614f7782856148fc565b610a9b6020830184614cdd565b8051610a3e81614860565b600060208284031215614fa457614fa4600080fd5b6000611b268484614f84565b634e487b7160e01b600052601160045260246000fd5b80820180821115610a3e57610a3e614fb0565b601f19601f83011681018181106001600160401b0382111715614ffe57614ffe614f53565b6040525050565b600061501060405190565b90506116ae8282614fd9565b6001600160801b03811661484a565b8051610a3e8161501c565b6001600160401b03811661484a565b8051610a3e81615036565b600060a0828403121561506557615065600080fd5b61506f60a0615005565b9050600061507d848461502b565b825250602061508e84848301615045565b60208301525060406150a284828501615045565b60408301525060606150b684828501614f84565b60608301525060806150ca84828501615045565b60808301525092915050565b600060a082840312156150eb576150eb600080fd5b6000611b268484615050565b6001600160401b0381166147b5565b60208101610a3e82846150f7565b6060810161512282866148fc565b61512f6020830185614b19565b611b2660408301846148fc565b6060810161514a8286614b19565b61512f60208301856148fc565b6040810161516582856148fc565b610a9b6020830184614b19565b81810381811115610a3e57610a3e614fb0565b8051610a3e81614910565b6000602082840312156151a5576151a5600080fd5b6000611b268484615185565b634e487b7160e01b600052601260045260246000fd5b6000826151d6576151d66151b1565b500490565b604081016151e98285614b19565b610a9b60208301846148fc565b604081016152048285614b19565b610a9b60208301846148e5565b6040810161520482856148e5565b604081016151658285614b19565b6080810161523b8287614b19565b6152486020830186614b19565b61525560408301856148fc565b61526260608301846148ae565b95945050505050565b600060ff8216610a3e565b6147b58161526b565b604081016151e98285615276565b6001600160701b03811661484a565b8051610a3e8161528d565b6000602082840312156152bc576152bc600080fd5b6000611b26848461529c565b6001600160701b0381166147b5565b606081016152e58286614b19565b6152f260208301856148e5565b611b2660408301846152c8565b634e487b7160e01b600052600160045260246000fd5b6000610a3e6147878381565b61532a83615315565b815460001960089490940293841b1916921b91909117905550565b6000610aae818484615321565b81811015610bd057615365600082615345565b600101615352565b601f821115610aae576000818152602090206020601f850104810160208510156153945750805b6119616020601f860104830182615352565b81516001600160401b038111156153bf576153bf614f53565b6153c98254614eb2565b6153d482828561536d565b6020601f83116001811461540857600084156153f05750858201515b600019600886021c1981166002860217865550613645565b600085815260208120601f198616915b828110156154385788850151825560209485019460019092019101615418565b868310156154545784890151600019601f89166008021c191682555b600160028802018855505050505050505050565b634e487b7160e01b600052602160045260246000fd5b60a0810161548c82886148fc565b61549960208301876148fc565b6154a660408301866148fc565b6154b360608301856148fc565b61429c6080830184614b19565b608081016154ce82876148fc565b6154db60208301866148e5565b6154e860408301856148fc565b61526260608301846148fc565b604081016151e982856148fc565b600061550d825190565b61551b8185602086016147c9565b9290920192915050565b6000610a9b8284615503565b6001600160d01b03918216919081169082820390811115610a3e57610a3e614fb0565b6001600160d01b03918216919081169082820190811115610a3e57610a3e614fb056fee8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d0052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300a2646970667358221220d72ec53a26ffe04ff3f3f62b720717fb053fe1e61e3336285511e759de4bd5ed64736f6c634300081800330000000000000000000000000000000000000000000000000000000068b58ac00000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583000000000000000000000000196fee96efeaad585483a6d950e70286b68519230000000000000000000000000000000000000000000000000000000000002710","name":"WorldLibertyFinancialV4","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"contracts/libraries/oz-v5/upgradeable/utils/cryptography/EIP712Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.20;\n\nimport {MessageHashUtils} from \"contracts/libraries/oz-v5/immutable/utils/cryptography/MessageHashUtils.sol\";\nimport {IERC5267} from \"contracts/libraries/oz-v5/immutable/interfaces/IERC5267.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose\n * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract\n * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to\n * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\n * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\n */\nabstract contract EIP712Upgradeable is Initializable, IERC5267 {\n    bytes32 private constant TYPE_HASH =\n        keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.EIP712\n    struct EIP712Storage {\n        /// @custom:oz-renamed-from _HASHED_NAME\n        bytes32 _hashedName;\n        /// @custom:oz-renamed-from _HASHED_VERSION\n        bytes32 _hashedVersion;\n\n        string _name;\n        string _version;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.EIP712\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant EIP712StorageLocation = 0xa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100;\n\n    function _getEIP712Storage() private pure returns (EIP712Storage storage $) {\n        assembly {\n            $.slot := EIP712StorageLocation\n        }\n    }\n\n    /**\n     * @dev Initializes the domain separator and parameter caches.\n     *\n     * The meaning of `name` and `version` is specified in\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n     *\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n     * - `version`: the current major version of the signing domain.\n     *\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n     * contract upgrade].\n     */\n    function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\n        __EIP712_init_unchained(name, version);\n    }\n\n    function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\n        EIP712Storage storage $ = _getEIP712Storage();\n        $._name = name;\n        $._version = version;\n\n        // Reset prior values in storage if upgrading\n        $._hashedName = 0;\n        $._hashedVersion = 0;\n    }\n\n    /**\n     * @dev Returns the domain separator for the current chain.\n     */\n    function _domainSeparatorV4() internal view returns (bytes32) {\n        return _buildDomainSeparator();\n    }\n\n    function _buildDomainSeparator() private view returns (bytes32) {\n        return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this)));\n    }\n\n    /**\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n     * function returns the hash of the fully encoded EIP712 message for this domain.\n     *\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n     *\n     * ```solidity\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n     *     keccak256(\"Mail(address to,string contents)\"),\n     *     mailTo,\n     *     keccak256(bytes(mailContents))\n     * )));\n     * address signer = ECDSA.recover(digest, signature);\n     * ```\n     */\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n        return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);\n    }\n\n    /**\n     * @dev See {IERC-5267}.\n     */\n    function eip712Domain()\n        public\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        EIP712Storage storage $ = _getEIP712Storage();\n        // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized\n        // and the EIP712 domain is not reliable, as it will be missing name and version.\n        require($._hashedName == 0 && $._hashedVersion == 0, \"EIP712: Uninitialized\");\n\n        return (\n            hex\"0f\", // 01111\n            _EIP712Name(),\n            _EIP712Version(),\n            block.chainid,\n            address(this),\n            bytes32(0),\n            new uint256[](0)\n        );\n    }\n\n    /**\n     * @dev The name parameter for the EIP712 domain.\n     *\n     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n     * are a concern.\n     */\n    function _EIP712Name() internal view virtual returns (string memory) {\n        EIP712Storage storage $ = _getEIP712Storage();\n        return $._name;\n    }\n\n    /**\n     * @dev The version parameter for the EIP712 domain.\n     *\n     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n     * are a concern.\n     */\n    function _EIP712Version() internal view virtual returns (string memory) {\n        EIP712Storage storage $ = _getEIP712Storage();\n        return $._version;\n    }\n\n    /**\n     * @dev The hash of the name parameter for the EIP712 domain.\n     *\n     * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead.\n     */\n    function _EIP712NameHash() internal view returns (bytes32) {\n        EIP712Storage storage $ = _getEIP712Storage();\n        string memory name = _EIP712Name();\n        if (bytes(name).length > 0) {\n            return keccak256(bytes(name));\n        } else {\n            // If the name is empty, the contract may have been upgraded without initializing the new storage.\n            // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design.\n            bytes32 hashedName = $._hashedName;\n            if (hashedName != 0) {\n                return hashedName;\n            } else {\n                return keccak256(\"\");\n            }\n        }\n    }\n\n    /**\n     * @dev The hash of the version parameter for the EIP712 domain.\n     *\n     * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead.\n     */\n    function _EIP712VersionHash() internal view returns (bytes32) {\n        EIP712Storage storage $ = _getEIP712Storage();\n        string memory version = _EIP712Version();\n        if (bytes(version).length > 0) {\n            return keccak256(bytes(version));\n        } else {\n            // If the version is empty, the contract may have been upgraded without initializing the new storage.\n            // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design.\n            bytes32 hashedVersion = $._hashedVersion;\n            if (hashedVersion != 0) {\n                return hashedVersion;\n            } else {\n                return keccak256(\"\");\n            }\n        }\n    }\n}\n"},{"file_path":"contracts/wlfi/interfaces/IWorldLibertyFinancialV3.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\n\nimport {IWorldLibertyFinancialV2} from \"./IWorldLibertyFinancialV2.sol\";\n\n\ninterface IWorldLibertyFinancialV3 is IWorldLibertyFinancialV2 {\n\n    // ==================================================\n    // ===================== Events =====================\n    // ==================================================\n\n    event VestingUpdated(address indexed account, uint8 oldCategory, uint8 newCategory);\n\n    // ==================================================\n    // ===================== Errors =====================\n    // ==================================================\n\n    error ElectionAlreadyPerformed();\n    error VesterNotInitialized(address account);\n    error TeamElectionWouldBlackoutClaims(address account);\n    error UnknownCategory(uint8 category);\n\n    // ==================================================\n    // ================ Owner Functions =================\n    // ==================================================\n\n    function ownerElectVestingUpdatesFor(address[] calldata _accounts) external;\n\n    // ==================================================\n    // ================ Public Functions ================\n    // ==================================================\n\n    /**\n     * @notice  Allows a user to perform a vesting update to a new category with finalized vesting terms\n     *\n     * @param   deadline    The deadline for the signature to be valid\n     * @param   _signature  The signature provided by `authorizedSigner` that proves the user accepted the vesting\n     *                      update\n     */\n    function electVestingUpdate(uint256 deadline, bytes calldata _signature) external;\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/utils/NoncesUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides tracking nonces for addresses. Nonces will only increment.\n */\nabstract contract NoncesUpgradeable is Initializable {\n    /**\n     * @dev The nonce used for an `account` is not the expected current nonce.\n     */\n    error InvalidAccountNonce(address account, uint256 currentNonce);\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.Nonces\n    struct NoncesStorage {\n        mapping(address account => uint256) _nonces;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Nonces\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant NoncesStorageLocation = 0x5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00;\n\n    function _getNoncesStorage() private pure returns (NoncesStorage storage $) {\n        assembly {\n            $.slot := NoncesStorageLocation\n        }\n    }\n\n    function __Nonces_init() internal onlyInitializing {\n    }\n\n    function __Nonces_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns the next unused nonce for an address.\n     */\n    function nonces(address owner) public view virtual returns (uint256) {\n        NoncesStorage storage $ = _getNoncesStorage();\n        return $._nonces[owner];\n    }\n\n    /**\n     * @dev Consumes a nonce.\n     *\n     * Returns the current value and increments nonce.\n     */\n    function _useNonce(address owner) internal virtual returns (uint256) {\n        NoncesStorage storage $ = _getNoncesStorage();\n        // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be\n        // decremented or reset. This guarantees that the nonce never overflows.\n        unchecked {\n            // It is important to do x++ and not ++x here.\n            return $._nonces[owner]++;\n        }\n    }\n\n    /**\n     * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.\n     */\n    function _useCheckedNonce(address owner, uint256 nonce) internal virtual {\n        uint256 current = _useNonce(owner);\n        if (nonce != current) {\n            revert InvalidAccountNonce(owner, current);\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC20Upgradeable} from \"../ERC20Upgradeable.sol\";\nimport {PausableUpgradeable} from \"../../../utils/PausableUpgradeable.sol\";\nimport {Initializable} from \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * IMPORTANT: This contract does not include public pause and unpause functions. In\n * addition to inheriting this contract, you must define both functions, invoking the\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\n * make the contract pause mechanism of the contract unreachable, and thus unusable.\n */\nabstract contract ERC20PausableUpgradeable is Initializable, ERC20Upgradeable, PausableUpgradeable {\n    function __ERC20Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __ERC20Pausable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev See {ERC20-_update}.\n     *\n     * Requirements:\n     *\n     * - the contract must not be paused.\n     */\n    function _update(address from, address to, uint256 value) internal virtual override whenNotPaused {\n        super._update(from, to, value);\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/access/OwnableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n    struct OwnableStorage {\n        address _owner;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n    function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n        assembly {\n            $.slot := OwnableStorageLocation\n        }\n    }\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    function __Ownable_init(address initialOwner) internal onlyInitializing {\n        __Ownable_init_unchained(initialOwner);\n    }\n\n    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        OwnableStorage storage $ = _getOwnableStorage();\n        return $._owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        OwnableStorage storage $ = _getOwnableStorage();\n        address oldOwner = $._owner;\n        $._owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/governance/utils/VotesUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (governance/utils/Votes.sol)\npragma solidity ^0.8.20;\n\nimport {IERC5805} from \"contracts/libraries/oz-v5/immutable/interfaces/IERC5805.sol\";\nimport {ContextUpgradeable} from \"../../utils/ContextUpgradeable.sol\";\nimport {NoncesUpgradeable} from \"../../utils/NoncesUpgradeable.sol\";\nimport {EIP712Upgradeable} from \"../../utils/cryptography/EIP712Upgradeable.sol\";\nimport {Checkpoints} from \"contracts/libraries/oz-v5/immutable/utils/structs/Checkpoints.sol\";\nimport {SafeCast} from \"contracts/libraries/oz-v5/immutable/utils/math/SafeCast.sol\";\nimport {ECDSA} from \"contracts/libraries/oz-v5/immutable/utils/cryptography/ECDSA.sol\";\nimport {Time} from \"contracts/libraries/oz-v5/immutable/utils/types/Time.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev This is a base abstract contract that tracks voting units, which are a measure of voting power that can be\n * transferred, and provides a system of vote delegation, where an account can delegate its voting units to a sort of\n * \"representative\" that will pool delegated voting units from different accounts and can then use it to vote in\n * decisions. In fact, voting units _must_ be delegated in order to count as actual votes, and an account has to\n * delegate those votes to itself if it wishes to participate in decisions and does not have a trusted representative.\n *\n * This contract is often combined with a token contract such that voting units correspond to token units. For an\n * example, see {ERC721Votes}.\n *\n * The full history of delegate votes is tracked on-chain so that governance protocols can consider votes as distributed\n * at a particular block number to protect against flash loans and double voting. The opt-in delegate system makes the\n * cost of this history tracking optional.\n *\n * When using this module the derived contract must implement {_getVotingUnits} (for example, make it return\n * {ERC721-balanceOf}), and can use {_transferVotingUnits} to track a change in the distribution of those units (in the\n * previous example, it would be included in {ERC721-_update}).\n */\nabstract contract VotesUpgradeable is Initializable, ContextUpgradeable, EIP712Upgradeable, NoncesUpgradeable, IERC5805 {\n    using Checkpoints for Checkpoints.Trace208;\n\n    bytes32 private constant DELEGATION_TYPEHASH =\n        keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.Votes\n    struct VotesStorage {\n        mapping(address account => address) _delegatee;\n\n        mapping(address delegatee => Checkpoints.Trace208) _delegateCheckpoints;\n\n        Checkpoints.Trace208 _totalCheckpoints;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Votes\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant VotesStorageLocation = 0xe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d00;\n\n    function _getVotesStorage() private pure returns (VotesStorage storage $) {\n        assembly {\n            $.slot := VotesStorageLocation\n        }\n    }\n\n    /**\n     * @dev The clock was incorrectly modified.\n     */\n    error ERC6372InconsistentClock();\n\n    /**\n     * @dev Lookup to future votes is not available.\n     */\n    error ERC5805FutureLookup(uint256 timepoint, uint48 clock);\n\n    function __Votes_init() internal onlyInitializing {\n    }\n\n    function __Votes_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based\n     * checkpoints (and voting), in which case {CLOCK_MODE} should be overridden as well to match.\n     */\n    function clock() public view virtual returns (uint48) {\n        return Time.blockNumber();\n    }\n\n    /**\n     * @dev Machine-readable description of the clock as specified in EIP-6372.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function CLOCK_MODE() public view virtual returns (string memory) {\n        // Check that the clock was not modified\n        if (clock() != Time.blockNumber()) {\n            revert ERC6372InconsistentClock();\n        }\n        return \"mode=blocknumber&from=default\";\n    }\n\n    /**\n     * @dev Returns the current amount of votes that `account` has.\n     */\n    function getVotes(address account) public view virtual returns (uint256) {\n        VotesStorage storage $ = _getVotesStorage();\n        return $._delegateCheckpoints[account].latest();\n    }\n\n    /**\n     * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is\n     * configured to use block numbers, this will return the value at the end of the corresponding block.\n     *\n     * Requirements:\n     *\n     * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.\n     */\n    function getPastVotes(address account, uint256 timepoint) public view virtual returns (uint256) {\n        VotesStorage storage $ = _getVotesStorage();\n        uint48 currentTimepoint = clock();\n        if (timepoint >= currentTimepoint) {\n            revert ERC5805FutureLookup(timepoint, currentTimepoint);\n        }\n        return $._delegateCheckpoints[account].upperLookupRecent(SafeCast.toUint48(timepoint));\n    }\n\n    /**\n     * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is\n     * configured to use block numbers, this will return the value at the end of the corresponding block.\n     *\n     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n     * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n     * vote.\n     *\n     * Requirements:\n     *\n     * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.\n     */\n    function getPastTotalSupply(uint256 timepoint) public view virtual returns (uint256) {\n        VotesStorage storage $ = _getVotesStorage();\n        uint48 currentTimepoint = clock();\n        if (timepoint >= currentTimepoint) {\n            revert ERC5805FutureLookup(timepoint, currentTimepoint);\n        }\n        return $._totalCheckpoints.upperLookupRecent(SafeCast.toUint48(timepoint));\n    }\n\n    /**\n     * @dev Returns the current total supply of votes.\n     */\n    function _getTotalSupply() internal view virtual returns (uint256) {\n        VotesStorage storage $ = _getVotesStorage();\n        return $._totalCheckpoints.latest();\n    }\n\n    /**\n     * @dev Returns the delegate that `account` has chosen.\n     */\n    function delegates(address account) public view virtual returns (address) {\n        VotesStorage storage $ = _getVotesStorage();\n        return $._delegatee[account];\n    }\n\n    /**\n     * @dev Delegates votes from the sender to `delegatee`.\n     */\n    function delegate(address delegatee) public virtual {\n        address account = _msgSender();\n        _delegate(account, delegatee);\n    }\n\n    /**\n     * @dev Delegates votes from signer to `delegatee`.\n     */\n    function delegateBySig(\n        address delegatee,\n        uint256 nonce,\n        uint256 expiry,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) public virtual {\n        if (block.timestamp > expiry) {\n            revert VotesExpiredSignature(expiry);\n        }\n        address signer = ECDSA.recover(\n            _hashTypedDataV4(keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry))),\n            v,\n            r,\n            s\n        );\n        _useCheckedNonce(signer, nonce);\n        _delegate(signer, delegatee);\n    }\n\n    /**\n     * @dev Delegate all of `account`'s voting units to `delegatee`.\n     *\n     * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.\n     */\n    function _delegate(address account, address delegatee) internal virtual {\n        VotesStorage storage $ = _getVotesStorage();\n        address oldDelegate = delegates(account);\n        $._delegatee[account] = delegatee;\n\n        emit DelegateChanged(account, oldDelegate, delegatee);\n        _moveDelegateVotes(oldDelegate, delegatee, _getVotingUnits(account));\n    }\n\n    /**\n     * @dev Transfers, mints, or burns voting units. To register a mint, `from` should be zero. To register a burn, `to`\n     * should be zero. Total supply of voting units will be adjusted with mints and burns.\n     */\n    function _transferVotingUnits(address from, address to, uint256 amount) internal virtual {\n        VotesStorage storage $ = _getVotesStorage();\n        if (from == address(0)) {\n            _push($._totalCheckpoints, _add, SafeCast.toUint208(amount));\n        }\n        if (to == address(0)) {\n            _push($._totalCheckpoints, _subtract, SafeCast.toUint208(amount));\n        }\n        _moveDelegateVotes(delegates(from), delegates(to), amount);\n    }\n\n    /**\n     * @dev Moves delegated votes from one delegate to another.\n     */\n    function _moveDelegateVotes(address from, address to, uint256 amount) private {\n        VotesStorage storage $ = _getVotesStorage();\n        if (from != to && amount > 0) {\n            if (from != address(0)) {\n                (uint256 oldValue, uint256 newValue) = _push(\n                    $._delegateCheckpoints[from],\n                    _subtract,\n                    SafeCast.toUint208(amount)\n                );\n                emit DelegateVotesChanged(from, oldValue, newValue);\n            }\n            if (to != address(0)) {\n                (uint256 oldValue, uint256 newValue) = _push(\n                    $._delegateCheckpoints[to],\n                    _add,\n                    SafeCast.toUint208(amount)\n                );\n                emit DelegateVotesChanged(to, oldValue, newValue);\n            }\n        }\n    }\n\n    /**\n     * @dev Get number of checkpoints for `account`.\n     */\n    function _numCheckpoints(address account) internal view virtual returns (uint32) {\n        VotesStorage storage $ = _getVotesStorage();\n        return SafeCast.toUint32($._delegateCheckpoints[account].length());\n    }\n\n    /**\n     * @dev Get the `pos`-th checkpoint for `account`.\n     */\n    function _checkpoints(\n        address account,\n        uint32 pos\n    ) internal view virtual returns (Checkpoints.Checkpoint208 memory) {\n        VotesStorage storage $ = _getVotesStorage();\n        return $._delegateCheckpoints[account].at(pos);\n    }\n\n    function _push(\n        Checkpoints.Trace208 storage store,\n        function(uint208, uint208) view returns (uint208) op,\n        uint208 delta\n    ) private returns (uint208, uint208) {\n        return store.push(clock(), op(store.latest(), delta));\n    }\n\n    function _add(uint208 a, uint208 b) private pure returns (uint208) {\n        return a + b;\n    }\n\n    function _subtract(uint208 a, uint208 b) private pure returns (uint208) {\n        return a - b;\n    }\n\n    /**\n     * @dev Must return the voting units held by an account.\n     */\n    function _getVotingUnits(address) internal view virtual returns (uint256);\n}\n"},{"file_path":"contracts/wlfi/interfaces/IWorldLibertyFinancialV4.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.24;\n\nimport {IWLFIStaking} from \"../../wlfi-staking/interfaces/IWLFIStaking.sol\";\nimport {IWorldLibertyFinancialV3} from \"./IWorldLibertyFinancialV3.sol\";\n\n/**\n * @title IWorldLibertyFinancialV4\n * @notice Interface for WLFI voting power from wallet balances, vesting, and the account's staking lock.\n * @dev Snapshot handles delegation. Voting power uses 18-decimal WLFI units.\n */\ninterface IWorldLibertyFinancialV4 is IWorldLibertyFinancialV3 {\n    // ==================================================\n    // ===================== Errors =====================\n    // ==================================================\n\n    error DelegationMovedToSnapshot();\n\n    error InvalidStakingContract();\n\n    error InvalidStakingVotingMultiplier();\n\n    // ==================================================\n    // =============== External Functions ===============\n    // ==================================================\n\n    /**\n     * @notice Delegation is configured in Snapshot.\n     * @param _delegatee Unused. Inherited from the Votes interface.\n     */\n    function delegate(address _delegatee) external;\n\n    /**\n     * @notice Signed delegation is configured in Snapshot.\n     * @param _delegatee Unused. Inherited from the Votes interface.\n     * @param _nonce Unused signer nonce from the inherited delegation format.\n     * @param _expiry Unused Unix timestamp, in seconds, from the inherited delegation format.\n     * @param _v Unused ECDSA recovery identifier.\n     * @param _r Unused ECDSA signature `r` value.\n     * @param _s Unused ECDSA signature `s` value.\n     */\n    function delegateBySig(address _delegatee, uint256 _nonce, uint256 _expiry, uint8 _v, bytes32 _r, bytes32 _s)\n        external;\n\n    /**\n     * @notice Returns the staking contract whose active lock contributes WLFI voting power.\n     * @return staking WLFI staking interface.\n     */\n    function WLFI_STAKING() external view returns (IWLFIStaking staking);\n\n    /**\n     * @notice Returns the voting score Snapshot must use before applying delegation.\n     * @dev Voting power is calculated as follows:\n     *\n     *      `stakePower = floor(activeStakedWLFI * stakingVotingMultiplierBps / 10_000)`\n     *\n     *      `votingPower = min(walletWLFI + unclaimedVestedWLFI + stakePower, MAX_VOTING_POWER)`\n     *\n     *      The staking multiplier is fixed at implementation deployment and does not depend on the initial or\n     *      remaining lock duration. It applies until unlock, including after the earliest withdrawal time.\n     *      After unlock, returned principal counts at its unweighted wallet amount. Claimed vesting tokens count\n     *      in the wallet instead of unclaimed vesting. The inherited cap applies to the combined score.\n     *      The zero address, excluded voters, and blacklisted voters have zero voting power.\n     * @param _account Account whose raw voting power is requested.\n     * @return votingPower Raw voting power in 18-decimal WLFI base units.\n     */\n    function getVotingPower(address _account) external view returns (uint256 votingPower);\n\n    /**\n     * @notice Returns lock voting power for a hypothetical stake of `_amountWei`.\n     * @param _amountWei Hypothetical locked WLFI, in 18-decimal base units.\n     * @return votingPower Lock voting power in 18-decimal WLFI base units.\n     */\n    function previewLockVotingPower(uint256 _amountWei) external view returns (uint256 votingPower);\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/interfaces/IERC5805.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5805.sol)\n\npragma solidity ^0.8.20;\n\nimport {IVotes} from \"../governance/utils/IVotes.sol\";\nimport {IERC6372} from \"./IERC6372.sol\";\n\ninterface IERC5805 is IERC6372, IVotes {}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/utils/math/SafeCast.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev An uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n}\n"},{"file_path":"contracts/wlfi/WorldLibertyFinancialV2.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\n\nimport {Ownable2StepUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport {ERC20Upgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport {ERC20BurnableUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol\";\nimport {ERC20PausableUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\";\nimport {ERC20VotesUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol\";\nimport {IERC20} from \"contracts/libraries/oz-v5/immutable/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"contracts/libraries/oz-v5/immutable/token/ERC20/utils/SafeERC20.sol\";\nimport {ECDSA} from \"contracts/libraries/oz-v5/immutable/utils/cryptography/ECDSA.sol\";\nimport {IWorldLibertyFinancialRegistry} from \"./interfaces/IWorldLibertyFinancialRegistry.sol\";\nimport {IWorldLibertyFinancialVester} from \"./interfaces/IWorldLibertyFinancialVester.sol\";\nimport {IWorldLibertyFinancialV2} from \"./interfaces/IWorldLibertyFinancialV2.sol\";\n\n\n/*\n#   ################################################################################################   #\n####          ##########################################################################           ###\n###########               #####################################################               ##########\n######################               ################################              #####################\n###############      ############           #####################           ############     ############\n####################                             ##############              ##           ################\n###########################   #########     WLFI     #######           #########    ######################\n#############################             #    ####              #             ##########################\n###################################                             ###                   #####################\n##############################################                     ####    ###############################\n####################################################                   ###############################\n##################################################                        ############################\n##############################################                   #####      ##########################\n*/\ncontract WorldLibertyFinancialV2 is\n    IWorldLibertyFinancialV2,\n    ERC20VotesUpgradeable,\n    ERC20PausableUpgradeable,\n    ERC20BurnableUpgradeable,\n    Ownable2StepUpgradeable\n{\n    using SafeERC20 for IERC20;\n\n    bytes32 private constant WLFIV2StorageLocation = keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.WLFIV2\")) - 1)) & ~bytes32(uint256(0xff));\n    bytes32 private constant ACTIVATION_TYPEHASH = keccak256(\"Activation(address account)\");\n\n    // ===================================================\n    // ================ Immutable Fields =================\n    // ===================================================\n\n    uint256 public immutable override TRADING_START_TIMESTAMP;\n    IWorldLibertyFinancialRegistry public immutable REGISTRY;\n    IWorldLibertyFinancialVester public immutable VESTER;\n\n    // ===================================================\n    // ================== Mutable Fields =================\n    // ===================================================\n\n    // ==========================================\n    /// @notice These are inherited from WLFI V1 and cannot be changed. Nor can their ordering be changed.\n    // ==========================================\n\n    /// @dev The max amount of voting power a single address can have\n    uint256 public override MAX_VOTING_POWER;\n    /// @dev Mapping of guardians. More info on this can be read in the interface declaration.\n    mapping(address => bool) private _guardians;\n    /// @dev    Mapping of allowed transfer agents before transferring can begin. More info on this can be read in the\n    ///         interface declaration.\n    mapping(address => bool) private _allowListStatus;\n    /// @dev Mapping of addresses that cannot vote. More info on this can be read in the interface declaration.\n    mapping(address => bool) private _excludedVotingPower;\n\n    modifier onlyGuardian() {\n        _checkGuardian();\n        _;\n    }\n\n    modifier notBlacklisted(address _account) {\n        _checkNotBlacklisted(_account);\n        _;\n    }\n\n    constructor(uint256 _startTimestamp, address _registry, address _vester) {\n        _disableInitializers();\n\n        TRADING_START_TIMESTAMP = _startTimestamp;\n        REGISTRY = IWorldLibertyFinancialRegistry(_registry);\n        VESTER = IWorldLibertyFinancialVester(_vester);\n    }\n\n    /**\n     * @notice Initialize World Liberty Financial (WLFI) Token\n     */\n    /// @custom:oz-upgrades-validate-as-initializer\n    function initialize(address _authorizedSigner) external reinitializer(/* version = */ 2) {\n        __EIP712_init(name(), \"2\");\n\n        V2 storage $ = _getStorage();\n        _ownerSetAuthorizedSigner($, _authorizedSigner);\n    }\n\n    // ===================================================\n    // ================= Owner Functions =================\n    // ===================================================\n\n    function ownerPause() external onlyOwner whenNotPaused {\n        _pause();\n    }\n\n    function ownerUnpause() external onlyOwner whenPaused {\n        _unpause();\n    }\n\n    function ownerSetAuthorizedSigner(address _authorizedSigner) external onlyOwner {\n        _ownerSetAuthorizedSigner(_getStorage(), _authorizedSigner);\n    }\n\n    function ownerSetGuardian(address _guardian, bool _status) external onlyOwner {\n        if (_guardian == address(0)) {\n            revert InvalidAccount();\n        }\n\n        _guardians[_guardian] = _status;\n        emit SetGuardian(_guardian, _status);\n    }\n\n    function ownerSetMaxVotingPower(uint256 _maxVotingPower) external onlyOwner {\n        if (_maxVotingPower > (5_000_000_000 * 1 ether)) {\n            revert InvalidMaxVotingPower();\n        }\n\n        MAX_VOTING_POWER = _maxVotingPower;\n        emit SetMaxVotingPower(_maxVotingPower);\n    }\n\n    function ownerSetTransferBeforeStartStatus(\n        address _account,\n        bool _isAllowed\n    ) external onlyOwner {\n        _allowListStatus[_account] = _isAllowed;\n        emit SetAllowListStatus(_account, _isAllowed);\n    }\n\n    function ownerSetVotingPowerExcludedStatus(\n        address _account,\n        bool _status\n    ) external onlyOwner {\n        _ownerSetVotingPowerExcludedStatus(_account, _status);\n    }\n\n    function ownerRescueTokens(\n        address _recipient,\n        address _token,\n        uint256 _value\n    ) external onlyOwner {\n        if (_recipient == address(0)) {\n            revert InvalidAccount();\n        }\n        if (_value == 0) {\n            revert InvalidValue();\n        }\n\n        uint256 balanceOfToken = IERC20(_token).balanceOf(address(this));\n        if (_value > balanceOfToken) {\n            _value = balanceOfToken;\n        }\n        IERC20(_token).safeTransfer(_recipient, _value);\n    }\n\n    function ownerReallocateFrom(\n        address _from,\n        address _to,\n        uint256 _value\n    ) external onlyOwner {\n        _ownerReallocateFrom(_from, _to, _value);\n    }\n\n    function ownerBatchReallocateFrom(\n        address[] calldata _fromChunk,\n        address[] calldata _toChunk,\n        uint256[] calldata _valueChunk\n    ) external onlyOwner {\n        if (_fromChunk.length == 0 || _fromChunk.length != _toChunk.length || _toChunk.length != _valueChunk.length) {\n            revert InvalidParameters();\n        }\n\n        for (uint256 i; i < _fromChunk.length; ++i) {\n            _ownerReallocateFrom(_fromChunk[i], _toChunk[i], _valueChunk[i]);\n        }\n    }\n\n    function ownerSetBlacklistStatus(address _account, bool _isBlacklisted) external onlyOwner {\n        _setBlacklistStatus(_account, _isBlacklisted);\n    }\n\n    function ownerActivateAccount(address _account, bool _bypassVester) external onlyOwner {\n        _activateAccount(_account,_bypassVester);\n    }\n\n    function ownerClaimVestFor(address _user) external whenNotPaused onlyOwner returns (uint256) {\n        return VESTER.wlfiClaimFor(_user);\n    }\n\n    function renounceOwnership() public override onlyOwner {\n        revert NotImplemented();\n    }\n\n    // ==================================================\n    // =============== Guardian Functions ===============\n    // ==================================================\n\n    function guardianPause() external onlyGuardian whenNotPaused {\n        _pause();\n    }\n\n    function guardianSetBlacklistStatus(address _account, bool _isBlacklisted) external onlyGuardian {\n        _setBlacklistStatus(_account, _isBlacklisted);\n    }\n\n    // ==================================================\n    // ================ Public Functions ================\n    // ==================================================\n\n    function activateAccount(bytes calldata _signature) external {\n        address account = _msgSender();\n        _validateSignatureForAccountActivationAndActivate(account, _signature);\n    }\n\n    function activateAccountAndClaimVest(bytes calldata _signature) external whenNotPaused returns (uint256) {\n        address account = _msgSender();\n        _validateSignatureForAccountActivationAndActivate(account, _signature);\n        if (VESTER.claimable(account) == 0) {\n            // Prevent reversion if there is nothing to claim. For a better UX\n            return 0;\n        }\n\n        return VESTER.wlfiClaimFor(_msgSender());\n    }\n\n    function claimVest() external whenNotPaused returns (uint256) {\n        // Note if the call flow changes here, beware that there is a {claim} function available on the Vester that can\n        // be called directly by the user\n        return VESTER.wlfiClaimFor(_msgSender());\n    }\n\n    function getAllowListStatus(\n        address _account\n    ) public view returns (bool) {\n        return _allowListStatus[_account];\n    }\n\n    function isGuardian(\n        address _guardian\n    ) public view returns (bool) {\n        return _guardians[_guardian];\n    }\n\n    function isVoterExcluded(\n        address _account\n    ) public view returns (bool excludedStatus) {\n        return _excludedVotingPower[_account];\n    }\n\n    function isBlacklisted(\n        address _account\n    ) public view returns (bool blacklistStatus) {\n        return _getStorage().blacklistStatus[_account];\n    }\n\n    function getVotes(\n        address _account\n    ) public view override returns (uint256) {\n        if (isVoterExcluded(_account) || isBlacklisted(_account)) {\n            return 0;\n        }\n\n        // Get delegated votes + vesting votes\n        // Tokens in the vester contract that are owned by `_account` cannot be delegated\n        uint256 votingPower = super.getVotes(_account) + VESTER.unclaimed(_account);\n\n        if (delegates(_account) == address(0)) {\n            // If the user has not delegated yet, add their balance to reduce UX burden of calling `delegate`\n            votingPower += super.balanceOf(_account);\n        }\n\n        if (votingPower > MAX_VOTING_POWER) {\n            return MAX_VOTING_POWER;\n        }\n        return votingPower;\n    }\n\n    function getPastVotes(address /* _account */, uint256 /* _timepoint */) public pure override returns (uint256) {\n        // The current voting set up does not work with getting past votes (this is due to the {balanceOf} check for\n        // undelegated wallets)\n        revert NotImplemented();\n    }\n\n    function isReadyToTransact(address _account) public view returns (bool) {\n        return !REGISTRY.isLegacyUser(_account) || REGISTRY.isLegacyUserAndIsActivated(_account);\n    }\n\n    function authorizedSigner() public view returns (address) {\n        return _getStorage().authorizedSigner;\n    }\n\n    function isAfterTradingStartTimestamp() public view returns (bool) {\n        return block.timestamp >= TRADING_START_TIMESTAMP;\n    }\n\n    // ==================================================\n    // =============== Internal Functions ===============\n    // ==================================================\n\n    function _delegate(\n        address _account,\n        address _delegatee\n    )\n        notBlacklisted(_msgSender())\n        notBlacklisted(_account)\n        notBlacklisted(_delegatee)\n        whenNotPaused\n        internal\n        override\n    {\n        if (isVoterExcluded(_account)) {\n            revert VoterIsExcluded(_account);\n        }\n        super._delegate(_account, _delegatee);\n    }\n\n    function _approve(\n        address _owner,\n        address _spender,\n        uint256 _value,\n        bool _emitEvent\n    )\n        notBlacklisted(_msgSender())\n        notBlacklisted(_owner)\n        notBlacklisted(_spender)\n        whenNotPaused\n        internal\n        override\n    {\n        super._approve(_owner, _spender, _value, _emitEvent);\n    }\n\n    function _update(\n        address _from,\n        address _to,\n        uint256 _value\n    )\n        notBlacklisted(_msgSender())\n        notBlacklisted(_from)\n        notBlacklisted(_to)\n        internal\n        override(\n            ERC20Upgradeable,\n            ERC20VotesUpgradeable,\n            ERC20PausableUpgradeable\n        )\n    {\n        if (_to == address(this)) {\n            revert InvalidAccount();\n        }\n\n        if (!isAfterTradingStartTimestamp()) {\n            if ((_msgSender() == address(VESTER) && _to == address(VESTER)) || _msgSender() == owner()) {\n                // GUARD STATEMENT\n                // Only `owner()` or `VESTER` can move tokens\n                return super._update(_from, _to, _value);\n            }\n\n            // GUARD STATEMENT #2\n            if (!_allowListStatus[_from]) {\n                revert TransferNotAllowedYet();\n            }\n\n            return super._update(_from, _to, _value);\n        }\n\n        if (REGISTRY.isLegacyUserAndIsNotActivated(_from) && _msgSender() != owner()) {\n            // The registry is updated prior to the transfer occurring, so we don't need to check if the funds are\n            // going to the vester\n            revert AccountNotActivated(_from);\n        }\n        if (REGISTRY.isLegacyUserAndIsNotActivated(_to)) {\n            revert AccountNotActivated(_to);\n        }\n\n        return super._update(_from, _to, _value);\n    }\n\n    function _ownerReallocateFrom(\n        address _from,\n        address _to,\n        uint256 _value\n    ) internal {\n        V2 storage $ = _getStorage();\n        bool blacklistStatus = $.blacklistStatus[_from];\n        if (blacklistStatus) {\n            _setBlacklistStatus(_from, false);\n        }\n\n        if (\n            REGISTRY.isLegacyUserAndIsNotActivated(_from)\n            && balanceOf(_from) != _value\n        ) {\n            // Legacy users must re-allocate their full balance if they are not activated\n            revert InvalidReallocation();\n        }\n        if (REGISTRY.isLegacyUser(_to)) {\n            revert CannotReallocateToLegacyUser(_from, _to);\n        }\n\n        if (_value != 0) {\n            _burn(_from, _value);\n            _mint(_to, _value);\n        }\n\n        bool isLegacyUser = false;\n        if (REGISTRY.isLegacyUserAndIsNotActivated(_from)) {\n            isLegacyUser = true;\n            REGISTRY.wlfiReallocateFrom(_from, _to);\n        } else if (REGISTRY.isLegacyUserAndIsActivated(_from)) {\n            isLegacyUser = true;\n            REGISTRY.wlfiReallocateFrom(_from, _to);\n            VESTER.wlfiReallocateFrom(_from, _to);\n        }\n\n        if (blacklistStatus) {\n            _setBlacklistStatus(_from, true);\n        }\n\n        emit Reallocated(_from, _to, _value, isLegacyUser);\n    }\n\n    function _ownerSetVotingPowerExcludedStatus(\n        address _account,\n        bool _isExcluded\n    ) internal {\n        if (_isExcluded) {\n            // Undelegate the user's voting power\n            _delegate(_account, address(0));\n        }\n\n        _excludedVotingPower[_account] = _isExcluded;\n        emit SetVotingPowerExcludedStatus(_account, _isExcluded);\n    }\n\n    function _setBlacklistStatus(address _account, bool _isBlacklisted) internal {\n        if (_isBlacklisted) {\n            // Undelegate the user's voting power\n            _delegate(_account, address(0));\n        }\n\n        _getStorage().blacklistStatus[_account] = _isBlacklisted;\n        emit SetBlacklistStatus(_account, _isBlacklisted);\n    }\n\n    function _ownerSetAuthorizedSigner(V2 storage $, address _authorizedSigner) internal {\n        if (_authorizedSigner == address(0)) {\n            revert InvalidAuthorizedSigner();\n        }\n\n        $.authorizedSigner = _authorizedSigner;\n        emit SetAuthorizedSigner(_authorizedSigner);\n    }\n\n    function _validateSignatureForAccountActivationAndActivate(address _account, bytes calldata _signature) internal {\n        bytes32 hash = _hashTypedDataV4(keccak256(abi.encode(ACTIVATION_TYPEHASH, _account)));\n\n        if (authorizedSigner() != ECDSA.recover(hash, _signature)) {\n            revert InvalidSignature();\n        }\n\n        _activateAccount(_account, /* _bypassVester = */ false);\n    }\n\n    function _activateAccount(address _account, bool _bypassVester) internal {\n        REGISTRY.wlfiActivateAccount(_account);\n        uint8 category = REGISTRY.getLegacyUserCategory(_account);\n        uint112 allocation = REGISTRY.getLegacyUserAllocation(_account);\n\n        if (!_bypassVester) {\n            // Reset the allowance\n            _approve(_account, address(VESTER), 0);\n            _approve(_account, address(VESTER), allocation);\n\n            VESTER.wlfiActivateVest(_account, category, allocation);\n            assert(allowance(_account, address(VESTER)) == 0);\n        }\n    }\n\n    function _checkGuardian() internal view {\n        address caller = _msgSender();\n        if (!_guardians[caller]) {\n            revert GuardianUnauthorizedAccount(caller);\n        }\n    }\n\n    function _checkNotBlacklisted(address _account) internal view {\n        if (_account != address(0) && _getStorage().blacklistStatus[_account]) {\n            revert Blacklisted(_account);\n        }\n    }\n\n    function _getStorage() private pure returns (V2 storage $) {\n        bytes32 location = WLFIV2StorageLocation;\n        assembly {\n            $.slot := location\n        }\n    }\n\n    uint256[50] private __gap; // reserve space for upgradeability storage slot. Inherited from WLFI V1\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/utils/Strings.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControlUpgradeable {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC20Permit} from \"../extensions/IERC20Permit.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev An operation with an ERC20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/interfaces/IERC6372.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC6372.sol)\n\npragma solidity ^0.8.20;\n\ninterface IERC6372 {\n    /**\n     * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).\n     */\n    function clock() external view returns (uint48);\n\n    /**\n     * @dev Description of the clock\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function CLOCK_MODE() external view returns (string memory);\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/interfaces/draft-IERC6093.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard ERC20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\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 ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC20Upgradeable} from \"../ERC20Upgradeable.sol\";\nimport {ContextUpgradeable} from \"../../../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {\n    function __ERC20Burnable_init() internal onlyInitializing {\n    }\n\n    function __ERC20Burnable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Destroys a `value` amount of tokens from the caller.\n     *\n     * See {ERC20-_burn}.\n     */\n    function burn(uint256 value) public virtual {\n        _burn(_msgSender(), value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, deducting from\n     * the caller's allowance.\n     *\n     * See {ERC20-_burn} and {ERC20-allowance}.\n     *\n     * Requirements:\n     *\n     * - the caller must have allowance for ``accounts``'s tokens of at least\n     * `value`.\n     */\n    function burnFrom(address account, uint256 value) public virtual {\n        _spendAllowance(account, _msgSender(), value);\n        _burn(account, value);\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/utils/math/SignedMath.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/utils/types/Time.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/types/Time.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"../math/Math.sol\";\nimport {SafeCast} from \"../math/SafeCast.sol\";\n\n/**\n * @dev This library provides helpers for manipulating time-related objects.\n *\n * It uses the following types:\n * - `uint48` for timepoints\n * - `uint32` for durations\n *\n * While the library doesn't provide specific types for timepoints and duration, it does provide:\n * - a `Delay` type to represent duration that can be programmed to change value automatically at a given point\n * - additional helper functions\n */\nlibrary Time {\n    using Time for *;\n\n    /**\n     * @dev Get the block timestamp as a Timepoint.\n     */\n    function timestamp() internal view returns (uint48) {\n        return SafeCast.toUint48(block.timestamp);\n    }\n\n    /**\n     * @dev Get the block number as a Timepoint.\n     */\n    function blockNumber() internal view returns (uint48) {\n        return SafeCast.toUint48(block.number);\n    }\n\n    // ==================================================== Delay =====================================================\n    /**\n     * @dev A `Delay` is a uint32 duration that can be programmed to change value automatically at a given point in the\n     * future. The \"effect\" timepoint describes when the transitions happens from the \"old\" value to the \"new\" value.\n     * This allows updating the delay applied to some operation while keeping some guarantees.\n     *\n     * In particular, the {update} function guarantees that if the delay is reduced, the old delay still applies for\n     * some time. For example if the delay is currently 7 days to do an upgrade, the admin should not be able to set\n     * the delay to 0 and upgrade immediately. If the admin wants to reduce the delay, the old delay (7 days) should\n     * still apply for some time.\n     *\n     *\n     * The `Delay` type is 112 bits long, and packs the following:\n     *\n     * ```\n     *   | [uint48]: effect date (timepoint)\n     *   |           | [uint32]: value before (duration)\n     *   ↓           ↓       ↓ [uint32]: value after (duration)\n     * 0xAAAAAAAAAAAABBBBBBBBCCCCCCCC\n     * ```\n     *\n     * NOTE: The {get} and {withUpdate} functions operate using timestamps. Block number based delays are not currently\n     * supported.\n     */\n    type Delay is uint112;\n\n    /**\n     * @dev Wrap a duration into a Delay to add the one-step \"update in the future\" feature\n     */\n    function toDelay(uint32 duration) internal pure returns (Delay) {\n        return Delay.wrap(duration);\n    }\n\n    /**\n     * @dev Get the value at a given timepoint plus the pending value and effect timepoint if there is a scheduled\n     * change after this timepoint. If the effect timepoint is 0, then the pending value should not be considered.\n     */\n    function _getFullAt(Delay self, uint48 timepoint) private pure returns (uint32, uint32, uint48) {\n        (uint32 valueBefore, uint32 valueAfter, uint48 effect) = self.unpack();\n        return effect <= timepoint ? (valueAfter, 0, 0) : (valueBefore, valueAfter, effect);\n    }\n\n    /**\n     * @dev Get the current value plus the pending value and effect timepoint if there is a scheduled change. If the\n     * effect timepoint is 0, then the pending value should not be considered.\n     */\n    function getFull(Delay self) internal view returns (uint32, uint32, uint48) {\n        return _getFullAt(self, timestamp());\n    }\n\n    /**\n     * @dev Get the current value.\n     */\n    function get(Delay self) internal view returns (uint32) {\n        (uint32 delay, , ) = self.getFull();\n        return delay;\n    }\n\n    /**\n     * @dev Update a Delay object so that it takes a new duration after a timepoint that is automatically computed to\n     * enforce the old delay at the moment of the update. Returns the updated Delay object and the timestamp when the\n     * new delay becomes effective.\n     */\n    function withUpdate(\n        Delay self,\n        uint32 newValue,\n        uint32 minSetback\n    ) internal view returns (Delay updatedDelay, uint48 effect) {\n        uint32 value = self.get();\n        uint32 setback = uint32(Math.max(minSetback, value > newValue ? value - newValue : 0));\n        effect = timestamp() + setback;\n        return (pack(value, newValue, effect), effect);\n    }\n\n    /**\n     * @dev Split a delay into its components: valueBefore, valueAfter and effect (transition timepoint).\n     */\n    function unpack(Delay self) internal pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {\n        uint112 raw = Delay.unwrap(self);\n\n        valueAfter = uint32(raw);\n        valueBefore = uint32(raw >> 32);\n        effect = uint48(raw >> 64);\n\n        return (valueBefore, valueAfter, effect);\n    }\n\n    /**\n     * @dev pack the components into a Delay object.\n     */\n    function pack(uint32 valueBefore, uint32 valueAfter, uint48 effect) internal pure returns (Delay) {\n        return Delay.wrap((uint112(effect) << 64) | (uint112(valueBefore) << 32) | uint112(valueAfter));\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/governance/utils/IVotes.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n */\ninterface IVotes {\n    /**\n     * @dev The signature used has expired.\n     */\n    error VotesExpiredSignature(uint256 expiry);\n\n    /**\n     * @dev Emitted when an account changes their delegate.\n     */\n    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n    /**\n     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of voting units.\n     */\n    event DelegateVotesChanged(address indexed delegate, uint256 previousVotes, uint256 newVotes);\n\n    /**\n     * @dev Returns the current amount of votes that `account` has.\n     */\n    function getVotes(address account) external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is\n     * configured to use block numbers, this will return the value at the end of the corresponding block.\n     */\n    function getPastVotes(address account, uint256 timepoint) external view returns (uint256);\n\n    /**\n     * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is\n     * configured to use block numbers, this will return the value at the end of the corresponding block.\n     *\n     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n     * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n     * vote.\n     */\n    function getPastTotalSupply(uint256 timepoint) external view returns (uint256);\n\n    /**\n     * @dev Returns the delegate that `account` has chosen.\n     */\n    function delegates(address account) external view returns (address);\n\n    /**\n     * @dev Delegates votes from the sender to `delegatee`.\n     */\n    function delegate(address delegatee) external;\n\n    /**\n     * @dev Delegates votes from signer to `delegatee`.\n     */\n    function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Votes.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC20Upgradeable} from \"../ERC20Upgradeable.sol\";\nimport {VotesUpgradeable} from \"../../../governance/utils/VotesUpgradeable.sol\";\nimport {Checkpoints} from \"contracts/libraries/oz-v5/immutable/utils/structs/Checkpoints.sol\";\nimport {Initializable} from \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,\n * and supports token supply up to 2^208^ - 1, while COMP is limited to 2^96^ - 1.\n *\n * NOTE: This contract does not provide interface compatibility with Compound's COMP token.\n *\n * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either\n * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting\n * power can be queried through the public accessors {getVotes} and {getPastVotes}.\n *\n * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it\n * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.\n */\nabstract contract ERC20VotesUpgradeable is Initializable, ERC20Upgradeable, VotesUpgradeable {\n    /**\n     * @dev Total supply cap has been exceeded, introducing a risk of votes overflowing.\n     */\n    error ERC20ExceededSafeSupply(uint256 increasedSupply, uint256 cap);\n\n    function __ERC20Votes_init() internal onlyInitializing {\n    }\n\n    function __ERC20Votes_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Maximum token supply. Defaults to `type(uint208).max` (2^208^ - 1).\n     *\n     * This maximum is enforced in {_update}. It limits the total supply of the token, which is otherwise a uint256,\n     * so that checkpoints can be stored in the Trace208 structure used by {{Votes}}. Increasing this value will not\n     * remove the underlying limitation, and will cause {_update} to fail because of a math overflow in\n     * {_transferVotingUnits}. An override could be used to further restrict the total supply (to a lower value) if\n     * additional logic requires it. When resolving override conflicts on this function, the minimum should be\n     * returned.\n     */\n    function _maxSupply() internal view virtual returns (uint256) {\n        return type(uint208).max;\n    }\n\n    /**\n     * @dev Move voting power when tokens are transferred.\n     *\n     * Emits a {IVotes-DelegateVotesChanged} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual override {\n        super._update(from, to, value);\n        if (from == address(0)) {\n            uint256 supply = totalSupply();\n            uint256 cap = _maxSupply();\n            if (supply > cap) {\n                revert ERC20ExceededSafeSupply(supply, cap);\n            }\n        }\n        _transferVotingUnits(from, to, value);\n    }\n\n    /**\n     * @dev Returns the voting units of an `account`.\n     *\n     * WARNING: Overriding this function may compromise the internal vote accounting.\n     * `ERC20Votes` assumes tokens map to voting units 1:1 and this is not easy to change.\n     */\n    function _getVotingUnits(address account) internal view virtual override returns (uint256) {\n        return balanceOf(account);\n    }\n\n    /**\n     * @dev Get number of checkpoints for `account`.\n     */\n    function numCheckpoints(address account) public view virtual returns (uint32) {\n        return _numCheckpoints(account);\n    }\n\n    /**\n     * @dev Get the `pos`-th checkpoint for `account`.\n     */\n    function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoints.Checkpoint208 memory) {\n        return _checkpoints(account, pos);\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/interfaces/IERC5267.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)\n\npragma solidity ^0.8.20;\n\ninterface IERC5267 {\n    /**\n     * @dev MAY be emitted to signal that the domain could have changed.\n     */\n    event EIP712DomainChanged();\n\n    /**\n     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\n     * signature.\n     */\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":"contracts/libraries/oz-v5/immutable/utils/structs/Checkpoints.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/Checkpoints.sol)\n// This file was procedurally generated from scripts/generate/templates/Checkpoints.js.\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"../math/Math.sol\";\n\n/**\n * @dev This library defines the `Trace*` struct, for checkpointing values as they change at different points in\n * time, and later looking up past values by block number. See {Votes} as an example.\n *\n * To create a history of checkpoints define a variable type `Checkpoints.Trace*` in your contract, and store a new\n * checkpoint for the current transaction block using the {push} function.\n */\nlibrary Checkpoints {\n    /**\n     * @dev A value was attempted to be inserted on a past checkpoint.\n     */\n    error CheckpointUnorderedInsertion();\n\n    struct Trace224 {\n        Checkpoint224[] _checkpoints;\n    }\n\n    struct Checkpoint224 {\n        uint32 _key;\n        uint224 _value;\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint.\n     *\n     * Returns previous value and new value.\n     *\n     * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint32).max` key set will disable the\n     * library.\n     */\n    function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) {\n        return _insert(self._checkpoints, key, value);\n    }\n\n    /**\n     * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if\n     * there is none.\n     */\n    function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     */\n    function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     *\n     * NOTE: This is a variant of {upperLookup} that is optimised to find \"recent\" checkpoint (checkpoints with high\n     * keys).\n     */\n    function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) {\n        uint256 len = self._checkpoints.length;\n\n        uint256 low = 0;\n        uint256 high = len;\n\n        if (len > 5) {\n            uint256 mid = len - Math.sqrt(len);\n            if (key < _unsafeAccess(self._checkpoints, mid)._key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);\n\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.\n     */\n    function latest(Trace224 storage self) internal view returns (uint224) {\n        uint256 pos = self._checkpoints.length;\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value\n     * in the most recent checkpoint.\n     */\n    function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) {\n        uint256 pos = self._checkpoints.length;\n        if (pos == 0) {\n            return (false, 0, 0);\n        } else {\n            Checkpoint224 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);\n            return (true, ckpt._key, ckpt._value);\n        }\n    }\n\n    /**\n     * @dev Returns the number of checkpoint.\n     */\n    function length(Trace224 storage self) internal view returns (uint256) {\n        return self._checkpoints.length;\n    }\n\n    /**\n     * @dev Returns checkpoint at given position.\n     */\n    function at(Trace224 storage self, uint32 pos) internal view returns (Checkpoint224 memory) {\n        return self._checkpoints[pos];\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,\n     * or by updating the last one.\n     */\n    function _insert(Checkpoint224[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {\n        uint256 pos = self.length;\n\n        if (pos > 0) {\n            // Copying to memory is important here.\n            Checkpoint224 memory last = _unsafeAccess(self, pos - 1);\n\n            // Checkpoint keys must be non-decreasing.\n            if (last._key > key) {\n                revert CheckpointUnorderedInsertion();\n            }\n\n            // Update or push new checkpoint\n            if (last._key == key) {\n                _unsafeAccess(self, pos - 1)._value = value;\n            } else {\n                self.push(Checkpoint224({_key: key, _value: value}));\n            }\n            return (last._value, value);\n        } else {\n            self.push(Checkpoint224({_key: key, _value: value}));\n            return (0, value);\n        }\n    }\n\n    /**\n     * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _upperBinaryLookup(\n        Checkpoint224[] storage self,\n        uint32 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key > key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or\n     * `high` if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and\n     * exclusive `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _lowerBinaryLookup(\n        Checkpoint224[] storage self,\n        uint32 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key < key) {\n                low = mid + 1;\n            } else {\n                high = mid;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.\n     */\n    function _unsafeAccess(\n        Checkpoint224[] storage self,\n        uint256 pos\n    ) private pure returns (Checkpoint224 storage result) {\n        assembly {\n            mstore(0, self.slot)\n            result.slot := add(keccak256(0, 0x20), pos)\n        }\n    }\n\n    struct Trace208 {\n        Checkpoint208[] _checkpoints;\n    }\n\n    struct Checkpoint208 {\n        uint48 _key;\n        uint208 _value;\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into a Trace208 so that it is stored as the checkpoint.\n     *\n     * Returns previous value and new value.\n     *\n     * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint48).max` key set will disable the\n     * library.\n     */\n    function push(Trace208 storage self, uint48 key, uint208 value) internal returns (uint208, uint208) {\n        return _insert(self._checkpoints, key, value);\n    }\n\n    /**\n     * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if\n     * there is none.\n     */\n    function lowerLookup(Trace208 storage self, uint48 key) internal view returns (uint208) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     */\n    function upperLookup(Trace208 storage self, uint48 key) internal view returns (uint208) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     *\n     * NOTE: This is a variant of {upperLookup} that is optimised to find \"recent\" checkpoint (checkpoints with high\n     * keys).\n     */\n    function upperLookupRecent(Trace208 storage self, uint48 key) internal view returns (uint208) {\n        uint256 len = self._checkpoints.length;\n\n        uint256 low = 0;\n        uint256 high = len;\n\n        if (len > 5) {\n            uint256 mid = len - Math.sqrt(len);\n            if (key < _unsafeAccess(self._checkpoints, mid)._key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);\n\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.\n     */\n    function latest(Trace208 storage self) internal view returns (uint208) {\n        uint256 pos = self._checkpoints.length;\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value\n     * in the most recent checkpoint.\n     */\n    function latestCheckpoint(Trace208 storage self) internal view returns (bool exists, uint48 _key, uint208 _value) {\n        uint256 pos = self._checkpoints.length;\n        if (pos == 0) {\n            return (false, 0, 0);\n        } else {\n            Checkpoint208 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);\n            return (true, ckpt._key, ckpt._value);\n        }\n    }\n\n    /**\n     * @dev Returns the number of checkpoint.\n     */\n    function length(Trace208 storage self) internal view returns (uint256) {\n        return self._checkpoints.length;\n    }\n\n    /**\n     * @dev Returns checkpoint at given position.\n     */\n    function at(Trace208 storage self, uint32 pos) internal view returns (Checkpoint208 memory) {\n        return self._checkpoints[pos];\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,\n     * or by updating the last one.\n     */\n    function _insert(Checkpoint208[] storage self, uint48 key, uint208 value) private returns (uint208, uint208) {\n        uint256 pos = self.length;\n\n        if (pos > 0) {\n            // Copying to memory is important here.\n            Checkpoint208 memory last = _unsafeAccess(self, pos - 1);\n\n            // Checkpoint keys must be non-decreasing.\n            if (last._key > key) {\n                revert CheckpointUnorderedInsertion();\n            }\n\n            // Update or push new checkpoint\n            if (last._key == key) {\n                _unsafeAccess(self, pos - 1)._value = value;\n            } else {\n                self.push(Checkpoint208({_key: key, _value: value}));\n            }\n            return (last._value, value);\n        } else {\n            self.push(Checkpoint208({_key: key, _value: value}));\n            return (0, value);\n        }\n    }\n\n    /**\n     * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _upperBinaryLookup(\n        Checkpoint208[] storage self,\n        uint48 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key > key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or\n     * `high` if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and\n     * exclusive `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _lowerBinaryLookup(\n        Checkpoint208[] storage self,\n        uint48 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key < key) {\n                low = mid + 1;\n            } else {\n                high = mid;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.\n     */\n    function _unsafeAccess(\n        Checkpoint208[] storage self,\n        uint256 pos\n    ) private pure returns (Checkpoint208 storage result) {\n        assembly {\n            mstore(0, self.slot)\n            result.slot := add(keccak256(0, 0x20), pos)\n        }\n    }\n\n    struct Trace160 {\n        Checkpoint160[] _checkpoints;\n    }\n\n    struct Checkpoint160 {\n        uint96 _key;\n        uint160 _value;\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint.\n     *\n     * Returns previous value and new value.\n     *\n     * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint96).max` key set will disable the\n     * library.\n     */\n    function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) {\n        return _insert(self._checkpoints, key, value);\n    }\n\n    /**\n     * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if\n     * there is none.\n     */\n    function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     */\n    function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {\n        uint256 len = self._checkpoints.length;\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero\n     * if there is none.\n     *\n     * NOTE: This is a variant of {upperLookup} that is optimised to find \"recent\" checkpoint (checkpoints with high\n     * keys).\n     */\n    function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) {\n        uint256 len = self._checkpoints.length;\n\n        uint256 low = 0;\n        uint256 high = len;\n\n        if (len > 5) {\n            uint256 mid = len - Math.sqrt(len);\n            if (key < _unsafeAccess(self._checkpoints, mid)._key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);\n\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.\n     */\n    function latest(Trace160 storage self) internal view returns (uint160) {\n        uint256 pos = self._checkpoints.length;\n        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;\n    }\n\n    /**\n     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value\n     * in the most recent checkpoint.\n     */\n    function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) {\n        uint256 pos = self._checkpoints.length;\n        if (pos == 0) {\n            return (false, 0, 0);\n        } else {\n            Checkpoint160 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);\n            return (true, ckpt._key, ckpt._value);\n        }\n    }\n\n    /**\n     * @dev Returns the number of checkpoint.\n     */\n    function length(Trace160 storage self) internal view returns (uint256) {\n        return self._checkpoints.length;\n    }\n\n    /**\n     * @dev Returns checkpoint at given position.\n     */\n    function at(Trace160 storage self, uint32 pos) internal view returns (Checkpoint160 memory) {\n        return self._checkpoints[pos];\n    }\n\n    /**\n     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,\n     * or by updating the last one.\n     */\n    function _insert(Checkpoint160[] storage self, uint96 key, uint160 value) private returns (uint160, uint160) {\n        uint256 pos = self.length;\n\n        if (pos > 0) {\n            // Copying to memory is important here.\n            Checkpoint160 memory last = _unsafeAccess(self, pos - 1);\n\n            // Checkpoint keys must be non-decreasing.\n            if (last._key > key) {\n                revert CheckpointUnorderedInsertion();\n            }\n\n            // Update or push new checkpoint\n            if (last._key == key) {\n                _unsafeAccess(self, pos - 1)._value = value;\n            } else {\n                self.push(Checkpoint160({_key: key, _value: value}));\n            }\n            return (last._value, value);\n        } else {\n            self.push(Checkpoint160({_key: key, _value: value}));\n            return (0, value);\n        }\n    }\n\n    /**\n     * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high`\n     * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive\n     * `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _upperBinaryLookup(\n        Checkpoint160[] storage self,\n        uint96 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key > key) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or\n     * `high` if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and\n     * exclusive `high`.\n     *\n     * WARNING: `high` should not be greater than the array's length.\n     */\n    function _lowerBinaryLookup(\n        Checkpoint160[] storage self,\n        uint96 key,\n        uint256 low,\n        uint256 high\n    ) private view returns (uint256) {\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n            if (_unsafeAccess(self, mid)._key < key) {\n                low = mid + 1;\n            } else {\n                high = mid;\n            }\n        }\n        return high;\n    }\n\n    /**\n     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.\n     */\n    function _unsafeAccess(\n        Checkpoint160[] storage self,\n        uint256 pos\n    ) private pure returns (Checkpoint160 storage result) {\n        assembly {\n            mstore(0, self.slot)\n            result.slot := add(keccak256(0, 0x20), pos)\n        }\n    }\n}\n"},{"file_path":"contracts/wlfi/interfaces/IWorldLibertyFinancialV2.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\n\nimport {ERC20Upgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport {ERC20PausableUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\";\nimport {ERC20BurnableUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol\";\nimport {ERC20VotesUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol\";\nimport {Ownable2StepUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport {IERC20} from \"contracts/libraries/oz-v5/immutable/token/ERC20/IERC20.sol\";\n\n\ninterface IWorldLibertyFinancialV2 is IERC20 {\n\n    // ==================================================\n    // ==================== Structs =====================\n    // ==================================================\n\n    struct V2 {\n        /// @dev Whether or not a user can approve or transfer tokens\n        mapping(address => bool) blacklistStatus;\n        address authorizedSigner;\n    }\n\n    // ==================================================\n    // ===================== Events =====================\n    // ==================================================\n\n    event SetAuthorizedSigner(address indexed authorizedSigner);\n    event SetGuardian(address indexed guardian, bool isGuardian);\n    event SetAllowListStatus(address indexed account, bool isTransferAllowed);\n    event SetVotingPowerExcludedStatus(address indexed account, bool isExcluded);\n    event SetBlacklistStatus(address indexed account, bool isBlacklisted);\n    event SetMaxVotingPower(uint256 maxVotingPower);\n    event Reallocated(address from, address to, uint256 amount, bool didTransferRegistry);\n\n    // ==================================================\n    // ===================== Errors =====================\n    // ==================================================\n\n    error AccountNotActivated(address account);\n    error Blacklisted(address account);\n    error DeadlineExpired();\n    error GuardianUnauthorizedAccount(address account);\n    error InvalidReallocation();\n    error CannotReallocateToLegacyUser(address from, address to);\n    error InvalidAccount();\n    error InvalidAuthorizedSigner();\n    error InvalidMaxVotingPower();\n    error InvalidParameters();\n    error InvalidSignature();\n    error InvalidValue();\n    error NotImplemented();\n    error TransferNotAllowedYet();\n    error VoterIsExcluded(address account);\n\n    // ==================================================\n    // ================== Initializers ==================\n    // ==================================================\n\n    function initialize(address _authorizedSigner) external;\n\n    // ===================================================\n    // ================= Owner Functions =================\n    // ===================================================\n\n    /**\n     * @notice Pauses token transfers and approvals on the WLFI token\n     * @dev Only owner can invoke this function\n     */\n    function ownerPause() external;\n\n    /**\n     * @notice Pauses token transfers and approvals on the WLFI token\n     * @dev Only owner can invoke this function\n     */\n    function ownerUnpause() external;\n\n    /**\n     * @notice  Set the authorized signer for this contract. This signer is used to enable the transferring of tokens by\n     *          \"Legacy Users\"\n     * @param _authorizedSigner The authorized signer address\n     * @dev Only owner can invoke this function\n     */\n    function ownerSetAuthorizedSigner(address _authorizedSigner) external;\n\n    /**\n     * @notice Set guardian status for address. Guardians are used to call `guardian`-designated functions\n     * @param _guardian Guardian address\n     * @param _status Guardian status\n     * @dev Only owner can invoke this function\n     */\n    function ownerSetGuardian(address _guardian, bool _status) external;\n\n    /**\n     * @notice Set max voting power\n     * @param _maxVotingPower Max voting power for an account\n     * @dev Only owner can invoke this function\n     */\n    function ownerSetMaxVotingPower(uint256 _maxVotingPower) external;\n\n    /**\n     * @notice  Set account transferability status. Only used before `START_TIMESTAMP` is passed by `block.timestamp`.\n     *          The storage for this function inherits state from V1 `_allowList`.\n     * @param _account The account whose status should be set\n     * @param _isAllowed True to allow transferring before `START_TIMESTAMP`. False to disallow it.\n     * @dev Only owner can invoke this function\n     */\n    function ownerSetTransferBeforeStartStatus(\n        address _account,\n        bool _isAllowed\n    ) external;\n\n    /**\n     * @notice Set excluded account voting power\n     * @param _account Account address\n     * @param _isExcluded True to exclude this user's voting power, false to include it\n     * @dev Only owner can invoke this function\n     */\n    function ownerSetVotingPowerExcludedStatus(\n        address _account,\n        bool _isExcluded\n    ) external;\n\n    /**\n     * @notice Rescue accidental tokens that are stuck in the contract\n     * @param _recipient Treasury address\n     * @param _token Token address\n     * @param _value Value to rescue\n     * @dev Only owner can invoke this function\n     */\n    function ownerRescueTokens(\n        address _recipient,\n        address _token,\n        uint256 _value\n    ) external;\n\n    /**\n     * @notice  Burn tokens from a malicious account without requiring allowance. Mints the corresponding tokens on the\n     *          other account. This is meant to be used only if a user loses access to their wallet prior to vesting\n     *          beginning or when a malicious account acquires WLFI via exploit. Emits the {Reallocated} event.\n     *\n     * @param _from Account address to burn tokens from\n     * @param _to Account address to mint the tokens to\n     * @param _value Amount of tokens to re-allocate\n     * @dev Only owner can invoke this function\n     */\n    function ownerReallocateFrom(\n        address _from,\n        address _to,\n        uint256 _value\n    ) external;\n\n    /**\n     * @notice  Burn tokens from a malicious account without requiring allowance. Mints the corresponding tokens on the\n     *          other account. This is meant to be used only if a user loses access to their wallet prior to vesting\n     *          beginning or when a malicious account acquires WLFI via exploit. Emits the {Reallocated} event.\n     *\n     * @param _fromChunk Account addresses to burn tokens from\n     * @param _toChunk Account addresses to mint the tokens to\n     * @param _valueChunk Amount of tokens to re-allocate for each from/to\n     * @dev Only owner can invoke this function. Reverts if the length of the arrays don't match or length is 0.\n     */\n    function ownerBatchReallocateFrom(\n        address[] calldata _fromChunk,\n        address[] calldata _toChunk,\n        uint256[] calldata _valueChunk\n    ) external;\n\n    /**\n     * @notice Blacklist an account from transacting with WLFI\n     * @dev Only owner can invoke this function\n     * @param _account The account whose blacklist status should be changed\n     * @param _isBlacklisted True to blacklist the account, false to remove it from the blacklist\n     */\n    function ownerSetBlacklistStatus(address _account, bool _isBlacklisted) external;\n\n    /**\n     * @notice  Activates a legacy user's vesting contract and moves their tokens into the vesting contract. Upon\n     *          activation, the user may begin sending or receiving WLFI tokens.\n     * @param _account      The legacy user that should be activated\n     * @param _bypassVester true if the user should bypass moving their funds into the vester and therefore be instantly\n     *                      unlocked. Setting this to false emulates the behavior from {activateAccount}. This parameter\n     *                      is mainly used for treasury assets or tokens that should remain under the user's control.\n     */\n    function ownerActivateAccount(address _account, bool _bypassVester) external;\n\n    /**\n     * @notice  Claims any available WLFI for `_user`\n     * @param _user The user whose vest should be claimed\n     * @return The amount of WLFI claimed for the caller\n     */\n    function ownerClaimVestFor(address _user) external returns (uint256);\n\n    // ==================================================\n    // =============== Guardian Functions ===============\n    // ==================================================\n\n    /**\n     * @notice Pauses token transfers and approvals on the WLFI token\n     * @dev Only a guardian can invoke this function\n     */\n    function guardianPause() external;\n\n    /**\n     * @notice Blacklist an account from transacting with WLFI\n     * @dev Only a guardian can invoke this function\n     */\n    function guardianSetBlacklistStatus(address _account, bool _isBlacklisted) external;\n\n    // ==================================================\n    // ================ Public Functions ================\n    // ==================================================\n\n    /**\n     * @notice  Activates a legacy user's vesting contract and moves their tokens into the vesting contract. Upon\n     *          activation, the user may begin sending or receiving WLFI tokens.\n     * @param _signature    The signature that was sent by the `authorizedSigner` amount of\n     */\n    function activateAccount(bytes calldata _signature) external;\n\n    /**\n     * @notice  Claims any available WLFI for `msg.sender`\n     * @return The amount of WLFI claimed for the caller\n     */\n    function claimVest() external returns (uint256);\n\n    /**\n     * @notice  Activates a user's account and claims any available WLFI for `msg.sender`\n     * @return The amount of WLFI claimed for the caller\n     */\n    function activateAccountAndClaimVest(bytes calldata _signature) external returns (uint256);\n\n    /**\n     * @notice Get account transferability status\n     * @param _sender Sender address\n     */\n    function getAllowListStatus(address _sender) external view returns (bool status);\n\n    /**\n     * @notice View authorized guardians\n     * @param _guardian Guardian address\n     */\n    function isGuardian(address _guardian) external view returns (bool guardianStatus);\n\n    /**\n     * @notice  Check if an address's voting power is excluded. If it is excluded, `balanceOfVotes` and\n     *          `getVotesWithBalanceFallback` will return 0 for the user\n     * @param _account The address of the account to check if their voting power is excluded\n     */\n    function isVoterExcluded(address _account) external view returns (bool excludedStatus);\n\n    /**\n     * @notice Check if an account is blacklisted\n     * @param _account The address of the account\n     */\n    function isBlacklisted(address _account) external view returns (bool blacklistStatus);\n\n    /**\n     * @notice  Checks if the provided `_account` is able to transfer or receive tokens\n     * @param _account  The account to check if its ready to transact\n     * @return  True fi the user can send or receive tokens. False if they are not able to yet.\n     */\n    function isReadyToTransact(address _account) external view returns (bool);\n\n    /**\n     * @return The address of the authorized signer that can approve a Legacy User's activation.\n     */\n    function authorizedSigner() external view returns (address);\n\n    /**\n     * @return True if the current block's timestamp is equal to or after the `TRADING_START_TIMESTAMP`.\n     */\n    function isAfterTradingStartTimestamp() external view returns (bool);\n\n    /**\n     * @return The max voting power an account can have\n     */\n    function MAX_VOTING_POWER() external view returns (uint256);\n\n    /**\n     * @return The timestamp at which trading and general transfers can begin for the WLFI token.\n     */\n    function TRADING_START_TIMESTAMP() external view returns (uint256);\n}\n"},{"file_path":"contracts/wlfi/WorldLibertyFinancialV3.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\n\nimport {Ownable2StepUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport {ERC20Upgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport {ERC20BurnableUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol\";\nimport {ERC20PausableUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\";\nimport {ERC20VotesUpgradeable} from \"contracts/libraries/oz-v5/upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol\";\nimport {IERC20} from \"contracts/libraries/oz-v5/immutable/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"contracts/libraries/oz-v5/immutable/token/ERC20/utils/SafeERC20.sol\";\nimport {ECDSA} from \"contracts/libraries/oz-v5/immutable/utils/cryptography/ECDSA.sol\";\nimport {IWorldLibertyFinancialRegistry} from \"./interfaces/IWorldLibertyFinancialRegistry.sol\";\nimport {IWorldLibertyFinancialVester} from \"./interfaces/IWorldLibertyFinancialVester.sol\";\nimport {IWorldLibertyFinancialV3} from \"./interfaces/IWorldLibertyFinancialV3.sol\";\nimport {WorldLibertyFinancialV2} from \"./WorldLibertyFinancialV2.sol\";\n\n\n/*\n#   ################################################################################################   #\n####          ##########################################################################           ###\n###########               #####################################################               ##########\n######################               ################################              #####################\n###############      ############           #####################           ############     ############\n####################                             ##############              ##           ################\n###########################   #########     WLFI     #######           #########    ######################\n#############################             #    ####              #             ##########################\n###################################                             ###                   #####################\n##############################################                     ####    ###############################\n####################################################                   ###############################\n##################################################                        ############################\n##############################################                   #####      ##########################\n*/\ncontract WorldLibertyFinancialV3 is\n    IWorldLibertyFinancialV3,\n    WorldLibertyFinancialV2\n{\n    using SafeERC20 for IERC20;\n\n    bytes32 private constant ELECTION_TYPEHASH = keccak256(\"Election(address account,uint256 deadline)\");\n\n    uint8 private constant EARLY_SUPPORTER_CATEGORY = 1;\n    uint8 public constant TERMINAL_RETAIL_CATEGORY = 45;\n    uint8 public constant TERMINAL_NON_RETAIL_CATEGORY = 47;\n\n    constructor(\n        uint256 _tradingStartTimestamp,\n        address _registry,\n        address _vester\n    ) WorldLibertyFinancialV2(_tradingStartTimestamp, _registry, _vester) {\n    }\n\n    // ==================================================\n    // ================= Owner Functions ================\n    // ==================================================\n\n    function ownerElectVestingUpdatesFor(address[] calldata _accounts) external onlyOwner whenNotPaused {\n        for (uint256 i; i < _accounts.length; ++i) {\n            _electVestingUpdate(_accounts[i]);\n        }\n    }\n\n    // ==================================================\n    // =============== External Functions ===============\n    // ==================================================\n\n    function electVestingUpdate(uint256 deadline, bytes calldata _signature) external whenNotPaused {\n        address account = _msgSender();\n        if (block.timestamp > deadline) {\n            revert DeadlineExpired();\n        }\n\n        bytes32 hash = _hashTypedDataV4(keccak256(abi.encode(ELECTION_TYPEHASH, account, deadline)));\n        if (authorizedSigner() != ECDSA.recover(hash, _signature)) {\n            revert InvalidSignature();\n        }\n\n        _electVestingUpdate(account);\n    }\n\n    // ==================================================\n    // ================ Public Functions ================\n    // ==================================================\n\n    function isKnownNonRetailCategory(uint8 _category) public pure returns (bool) {\n        return _category >= 2 && _category <= 20;\n    }\n\n    // ==================================================\n    // =============== Internal Functions ===============\n    // ==================================================\n\n    function _electVestingUpdate(address _account) internal {\n        if (!REGISTRY.isLegacyUser(_account)) {\n            revert InvalidAccount();\n        }\n        if (REGISTRY.isLegacyUserAndIsNotActivated(_account)) {\n            revert AccountNotActivated(_account);\n        }\n        if (VESTER.allocation(_account) == 0) {\n            revert VesterNotInitialized(_account);\n        }\n\n        uint8 oldCategory = REGISTRY.getLegacyUserCategory(_account);\n        if (oldCategory == TERMINAL_RETAIL_CATEGORY || oldCategory == TERMINAL_NON_RETAIL_CATEGORY) {\n            revert ElectionAlreadyPerformed();\n        }\n\n        uint8 newCategory;\n        if (oldCategory == EARLY_SUPPORTER_CATEGORY) {\n            newCategory = TERMINAL_RETAIL_CATEGORY;\n        } else if (isKnownNonRetailCategory(oldCategory)) {\n            newCategory = TERMINAL_NON_RETAIL_CATEGORY;\n        } else {\n            revert UnknownCategory(oldCategory);\n        }\n\n        if (newCategory == TERMINAL_NON_RETAIL_CATEGORY) {\n            uint256 allocation = VESTER.allocation(_account);\n            uint256 amountToBurn = allocation / 10;\n            uint256 alreadyClaimed = VESTER.claimed(_account);\n            if (alreadyClaimed > 0) {\n                revert TeamElectionWouldBlackoutClaims(_account);\n            }\n\n            VESTER.wlfiBurnAllocation(_account, amountToBurn);\n            REGISTRY.wlfiBurnAllocation(_account, amountToBurn);\n        }\n\n        VESTER.wlfiSetCategory(_account, newCategory);\n        REGISTRY.wlfiSetCategory(_account, newCategory);\n\n        emit VestingUpdated(_account, oldCategory, newCategory);\n    }\n}\n"},{"file_path":"contracts/wlfi/interfaces/IWorldLibertyFinancialVester.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\n\n\ninterface IWorldLibertyFinancialVester {\n\n    // ==================================================\n    // ==================== Structs =====================\n    // ==================================================\n\n    // One slot: 112 + 112 + 8 + 8 = 240 bits\n    struct UserInfo {\n        /// @dev total allocation for this user (all segments combined)\n        uint112 allocation;\n        /// @dev total claimed so far\n        uint112 claimed;\n        /// @dev user category\n        uint8 category;\n        /// @dev set at first by the user\n        bool initialized;\n    }\n\n    // One slot: 112 + 32 + 32 + 32 = 208 bits\n    struct Template {\n        /// @dev percentage cap for this segment; 1 ether (10 ** 18) equals 100%. The sum of all\n        ///      `percentageOfAllocation` for a category should be <= 1 ether (100%)\n        uint112 percentageOfAllocation;\n        /// @dev linear start (unix time)\n        uint32  startTimestamp;\n        /// @dev first moment any unlocks; usually == start for cliffed-linear\n        uint32  cliffTimestamp;\n        /// @dev linear end (unix time)\n        uint32  endTimestamp;\n    }\n\n    struct CategoryInfo {\n        /// @dev Numbered from 0..8\n        uint8 templateCount;\n        /// @dev True if this category is enabled or not yet\n        bool enabled;\n    }\n\n    struct VesterStorage {\n        /// @dev Up to 8 templates per category, index order = priority (0 highest → 7 lowest).\n        mapping(uint8 => Template[8]) categoryTemplates;\n        /// @dev Category ID to CategoryInfo\n        mapping(uint8 => CategoryInfo) categoryInfo;\n        /// @dev All of the legacy users that have activated their vesting account\n        mapping(address => UserInfo) users;\n        /// @dev The total amount of WLFI that have been claimed by users against this vesting contract\n        uint112 totalClaimed;\n        /// @dev The total amount of WLFI that have been allocated to users for this vesting contract\n        uint112 totalAllocated;\n    }\n\n    // ==================================================\n    // ===================== Events =====================\n    // ==================================================\n\n    event VestActivated(address indexed account, uint8 category, uint112 allocation);\n    event VestCategoryUpdated(address indexed account, uint8 oldCategory, uint8 newCategory);\n    event VestBurned(address indexed account, uint112 delta, uint112 newAllocation);\n    event VestTransferred(address indexed from, address indexed to);\n    event SetCategoryTemplate(uint8 indexed category, uint8 indexed index, Template t);\n    event SetCategoryEnabled(uint8 indexed category, bool enabled);\n    event SetCategoryTemplateCount(uint8 indexed category, uint8 count);\n    event Claimed(address indexed user, uint256 amount);\n\n    // ==================================================\n    // ===================== Errors =====================\n    // ==================================================\n\n    error Unauthorized();\n    error InvalidParameters();\n    error InvalidTemplateCount();\n    error InvalidTemplateTimestamp();\n    error InvalidTotalTemplatePercentage();\n    error InvalidUser(address user);\n    error CategoryNotEnabled(uint8 category);\n    error AlreadyInitialized(address user);\n    error UserNotInitialized(address user);\n    error NothingToClaim();\n\n    // ==================================================\n    // ================== Initializers ==================\n    // ==================================================\n\n    function initialize() external;\n\n    // ==================================================\n    // ================= Owner Functions ================\n    // ==================================================\n\n    /**\n     * @notice Pause user claims and vest activations.\n     * @dev Owner-only guardian switch. Paused state blocks {claim} but allows admin maintenance.\n     *\n     * @custom:reverts OwnableUnauthorizedAccount   If the caller is not the contract owner.\n     * @custom:reverts AlreadyPaused                If the contract is already paused.\n     */\n    function ownerPause() external;\n\n    /**\n     * @notice Unpause user claims.\n     * @dev Owner-only guardian switch. Restores {claim} functionality.\n     *\n     * @custom:reverts OwnableUnauthorizedAccount   If the caller is not the contract owner.\n     * @custom:reverts NotPaused                    If the contract is not currently paused.\n     */\n    function ownerUnpause() external;\n\n    /**\n     * @notice Enables a category so their vests may be activated.\n     *\n     * @param _category The category ID (uint8) that is being enabled\n     * @param _enabled  True to enable the category, false to disable it.\n     *\n     * @custom:reverts OwnableUnauthorizedAccount   If the caller is not the contract owner.\n     * @custom:reverts NotPaused                    If the contract is not currently paused.\n     */\n    function ownerSetCategoryEnabled(uint8 _category, bool _enabled) external;\n\n    /**\n     * @notice Configure or update a vesting template for a given category at a given priority index.\n     * @dev Each category supports up to 8 template slots (priority order: index 0 highest → 7 lowest).\n     *      The `_template` struct uses:\n     *        - percentageOfAllocation (uint112):\n     *              percentage cap for this segment; 1 ether (10 ** 18) equals 100%. The sum of all\n     *              `percentageOfAllocation` for a category should be <= 1 ether (100%)\n     *        - startTimestamp (uint32)\n     *        - cliffTimestamp (uint32)\n     *        - endTimestamp (uint32)\n     *              The vesting schedule; linear from (startTimestamp → endTimestamp); cliffTimestamp must be greater\n     *              than or equal to startTimestamp.\n     *      Setting a higher index than the current count increases the active template count for that category.\n     *\n     * @param _category  The category ID (uint8) being configured.\n     * @param _index     The priority index to set (0..3).\n     * @param _template  The vesting template parameters for this slot.\n     *\n     * @custom:reverts OwnableUnauthorizedAccount   If the caller is not the contract owner.\n     * @custom:reverts IndexOutOfRange              If `_index` >= 8.\n     * @custom:reverts InvalidTimeOrdering          If `_template.endTimestamp` != 0 and\n     *                                              (startTimestamp > cliffTimestamp || cliffTimestamp > endTimestamp).\n     */\n    function ownerSetCategoryTemplate(uint8 _category, uint8 _index, Template calldata _template) external;\n\n    // ==================================================\n    // =============== Guardian Functions ===============\n    // ==================================================\n\n    /**\n     * @notice Pause vest activation, user claims, owner-assisted claims.\n     * @dev Guardian-only circuit breaker. When paused, user-facing functions\n     *      (e.g., {claim}, {wlfiActivateVest}, {ownerClaimFor}) MUST revert. Administrative configuration\n     *      (e.g., setting templates) may remain allowed depending on implementation.\n     *\n     * @custom:reverts GuardianUnauthorizedAccount  If the caller is not the designated guardian.\n     * @custom:reverts EnforcedPause                If the contract is already in the paused state.\n     */\n    function guardianPause() external;\n\n    // ==================================================\n    // =============== External Functions ===============\n    // ==================================================\n\n    /**\n     * @notice Activate a user's WLFI vest using offchain–curated data.\n     * @dev Callable by the the WLFI token only and used to set up a user's vesting info as well as transfer a Legacy\n     *      User's vesting allocation into this vesting contract. Once a user is activated, they can begin calling\n     *      {claim}.\n     *\n     * @param _user      The beneficiary to activate.\n     * @param _category  The category the user belongs to.\n     * @param _amount    The total WLFI allocation for this user (uint112).\n     *\n     * @custom:reverts Unauthorized           If the caller is not the WLFI token.\n     * @custom:reverts InvalidParameters      If `_user` is the zero address, `_category` is 0, or `_amount` is zero.\n     * @custom:reverts AlreadyInitialized     If `_user` is already activated their vest.\n     */\n    function wlfiActivateVest(address _user, uint8 _category, uint112 _amount) external;\n\n    /**\n     * @notice  Allows the WLFI token to reduce a user's allocation of locked tokens. Emits `VestBurned`\n     *\n     * @param _user     The address of the user whose allocation will be reduced\n     * @param _amount   The amount to reduce the allocation by\n     */\n    function wlfiBurnAllocation(address _user, uint256 _amount) external;\n\n    /**\n     * @notice Claim ALL currently available (vested & unclaimed) WLFI for `_user`.\n     * @dev Pulls the user’s category pipeline, computes unlocked amounts across up to 8 template\n     *      segments in order, subtracts `claimed`, and transfers the claimable amount to the user.\n     *      If nothing is claimable, reverts with `NothingToClaim`.\n     *\n     * @param _user    The user whose vest should be claimed\n     * @return amount  The amount of WLFI transferred to the user for this claim.\n     *\n     * @custom:reverts Unauthorized           If the caller is not the WLFI token.\n     * @custom:reverts EnforcedPause          If the contract is paused.\n     * @custom:reverts UserNotInitialized     If the user has not been initialized (see {wlfiActivateVest}).\n     * @custom:reverts NothingToClaim         If the user's claimable amount is 0\n     */\n    function wlfiClaimFor(address _user) external returns (uint256);\n\n    /**\n     * @notice Reassign a vested account’s ownership from one address to another within the vesting contract.\n     * @dev Admin-only maintenance. Moves the in-contract accounting record for `_from` to `_to`\n     *      without transferring any tokens. The fields `{allocation, claimed, category, initialized}`\n     *      are copied so that the user’s remaining claimable balance is preserved exactly under `_to`.\n     *      Intended for support cases (e.g., lost wallets). Does not modify category or totals.\n     *\n     * @param _from  The current owner of the vested account record.\n     * @param _to    The new owner that will assume the vested account record.\n     *\n     * @custom:effects Copies the entire `UserInfo` for `_from` to `_to`, then clears `_from`’s record.\n     *                 No ERC20 transfer occurs. After reallocation, `_to` can call {claim}.\n     *\n     * @custom:reverts NotAuthorized          If the caller lacks permission to reallocate vest records.\n     * @custom:reverts ZeroAddress            If `_to` is the zero address.\n     * @custom:reverts SameAddress            If `_to` equals `_from`.\n     * @custom:reverts FromNotInitialized     If `_from` has no initialized vesting record in this contract.\n     * @custom:reverts ToAlreadyInitialized   If `_to` already has a vesting record (initialized or non-empty).\n     * @custom:reverts Paused                 (If implemented) If the contract is paused and reallocations are disallowed.\n     *\n     * @dev Optional policy notes:\n     *      - If your policy requires the new owner to explicitly acknowledge terms, you may reset\n     *        `initialized` to false during the move so `_to` must re-initialize before claiming.\n     *      - If you disallow moving fully claimed records, add and document `NothingToReallocate`\n     *        when `allocation == claimed`.\n     */\n    function wlfiReallocateFrom(address _from, address _to) external;\n\n    /**\n     * @notice  Allows the WLFI token to change a user's vesting category. Emits `VestCategoryUpdated`\n     *\n     * @param _user     The user whose vesting category should change\n     * @param _category The user's new vesting category\n     */\n    function wlfiSetCategory(address _user, uint8 _category) external;\n\n    /**\n     * @notice View the amount currently claimable by a user.\n     * @dev Purely a read: computes unlocked across the user’s category templates and subtracts `claimed`.\n     *      Returns 0 for users who are not initialized.\n     *\n     * @param _user The address to query.\n     * @return      The currently claimable WLFI for `_user`.\n     */\n    function claimable(address _user) external view returns (uint256);\n\n    /**\n     * @notice View the amount that has been claimed by a user.\n     * @dev Purely a read: computes how many tokens were `claimed`. Returns 0 for users who are not initialized.\n     *\n     * @param _user The address to query.\n     * @return      The amount of WLFI claimed for `_user`.\n     */\n    function claimed(address _user) external view returns (uint256);\n\n    /**\n     * @notice View the amount that has been allocated to a user.  Returns 0 for users who are not initialized.\n     * @dev Purely a read: computes how many tokens were `claimed`. Returns 0 for users who are not initialized.\n     *\n     * @param _user The address to query.\n     * @return      The amount of WLFI that has been allocated for `_user`.\n     */\n    function allocation(address _user) external view returns (uint256);\n\n    /**\n     * @notice View the amount that has been unclaimed by the user.  Returns 0 for users who are not initialized.\n     * @dev Purely a read: computes how many tokens were `unclaimed`. Returns 0 for users who are not initialized.\n     *\n     * @param _user The address to query.\n     * @return      The amount of WLFI that has been allocated to the `_user` and unclaimed.\n     */\n    function unclaimed(address _user) external view returns (uint256);\n\n    /**\n     * @return  The total amount of WLFI tokens that have been claimed by users\n     */\n    function totalClaimed() external view returns (uint256);\n\n    /**\n     * @return  The total amount of WLFI tokens that have been allocated to users who have activated their wallets\n     */\n    function totalAllocated() external view returns (uint256);\n\n    /**\n     * @return  The total amount of WLFI tokens that have been allocated to users and are unclaimed\n     */\n    function totalUnclaimed() external view returns (uint256);\n\n    /**\n     * @param _category The category whose info should be retrieved.\n     * @return The category info for a given category\n     */\n    function getCategoryInfo(uint8 _category) external view returns (CategoryInfo memory);\n\n    /**\n     * @param _category The category whose template count should be retrieved.\n     * @return The number of templates that this category has\n     */\n    function getCategoryTemplateCount(uint8 _category) external view returns (uint256);\n\n    /**\n     * @param _category The category whose enabled status should be retrieved.\n     * @return Whether or not this category is enabled and users who are in this category may move WLFI tokens into the\n     *         vester.\n     */\n    function getCategoryEnabled(uint8 _category) external view returns (bool);\n\n    /**\n     * @param _category The category whose info should be retrieved.\n     * @return All of the templates for a given category. The max length of the array is 8.\n     */\n    function getAllCategoryTemplates(uint8 _category) external view returns (Template[] memory);\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/token/ERC20/ERC20Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"contracts/libraries/oz-v5/immutable/token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"contracts/libraries/oz-v5/immutable/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {ContextUpgradeable} from \"../../utils/ContextUpgradeable.sol\";\nimport {IERC20Errors} from \"contracts/libraries/oz-v5/immutable/interfaces/draft-IERC6093.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n */\nabstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {\n    /// @custom:storage-location erc7201:openzeppelin.storage.ERC20\n    struct ERC20Storage {\n        mapping(address account => uint256) _balances;\n\n        mapping(address account => mapping(address spender => uint256)) _allowances;\n\n        uint256 _totalSupply;\n\n        string _name;\n        string _symbol;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ERC20\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;\n\n    function _getERC20Storage() private pure returns (ERC20Storage storage $) {\n        assembly {\n            $.slot := ERC20StorageLocation\n        }\n    }\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n        __ERC20_init_unchained(name_, symbol_);\n    }\n\n    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n        ERC20Storage storage $ = _getERC20Storage();\n        $._name = name_;\n        $._symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `value`.\n     */\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `value`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `value`.\n     */\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, value);\n        _transfer(from, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _transfer(address from, address to, uint256 value) internal {\n        if (from == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        if (to == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(from, to, value);\n    }\n\n    /**\n     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n     * this function.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual {\n        ERC20Storage storage $ = _getERC20Storage();\n        if (from == address(0)) {\n            // Overflow check required: The rest of the code assumes that totalSupply never overflows\n            $._totalSupply += value;\n        } else {\n            uint256 fromBalance = $._balances[from];\n            if (fromBalance < value) {\n                revert ERC20InsufficientBalance(from, fromBalance, value);\n            }\n            unchecked {\n                // Overflow not possible: value <= fromBalance <= totalSupply.\n                $._balances[from] = fromBalance - value;\n            }\n        }\n\n        if (to == address(0)) {\n            unchecked {\n                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n                $._totalSupply -= value;\n            }\n        } else {\n            unchecked {\n                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n                $._balances[to] += value;\n            }\n        }\n\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n     * Relies on the `_update` mechanism\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _mint(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(address(0), account, value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n     * Relies on the `_update` mechanism.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead\n     */\n    function _burn(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        _update(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        _approve(owner, spender, value, true);\n    }\n\n    /**\n     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n     *\n     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\n     * `Approval` event during `transferFrom` operations.\n     *\n     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\n     * true using the following override:\n     * ```\n     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n     *     super._approve(owner, spender, value, true);\n     * }\n     * ```\n     *\n     * Requirements are the same as {_approve}.\n     */\n    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n        ERC20Storage storage $ = _getERC20Storage();\n        if (owner == address(0)) {\n            revert ERC20InvalidApprover(address(0));\n        }\n        if (spender == address(0)) {\n            revert ERC20InvalidSpender(address(0));\n        }\n        $._allowances[owner][spender] = value;\n        if (emitEvent) {\n            emit Approval(owner, spender, value);\n        }\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `value`.\n     *\n     * Does not update the allowance value in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Does not emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            if (currentAllowance < value) {\n                revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n            }\n            unchecked {\n                _approve(owner, spender, currentAllowance - value, false);\n            }\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/token/ERC20/extensions/IERC20Permit.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\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     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        assembly {\n            $.slot := INITIALIZABLE_STORAGE\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/utils/cryptography/ECDSA.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS\n    }\n\n    /**\n     * @dev The signature derives the `address(0)`.\n     */\n    error ECDSAInvalidSignature();\n\n    /**\n     * @dev The signature has an invalid length.\n     */\n    error ECDSAInvalidSignatureLength(uint256 length);\n\n    /**\n     * @dev The signature has an S value that is in the upper half order.\n     */\n    error ECDSAInvalidSignatureS(bytes32 s);\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\n     * return address(0) without also returning an error description. Errors are documented using an enum (error type)\n     * and a bytes32 providing additional information about the error.\n     *\n     * If no error is returned, then the address can be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use 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            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     */\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {\n        unchecked {\n            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\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            return tryRecover(hash, v, r, s);\n        }\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     */\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError, bytes32) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. 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}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS, s);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature, bytes32(0));\n        }\n\n        return (signer, RecoverError.NoError, bytes32(0));\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\n     */\n    function _throwError(RecoverError error, bytes32 errorArg) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert ECDSAInvalidSignature();\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert ECDSAInvalidSignatureLength(uint256(errorArg));\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert ECDSAInvalidSignatureS(errorArg);\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/access/Ownable2StepUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {OwnableUpgradeable} from \"./OwnableUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable2Step\n    struct Ownable2StepStorage {\n        address _pendingOwner;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable2Step\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant Ownable2StepStorageLocation = 0x237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00;\n\n    function _getOwnable2StepStorage() private pure returns (Ownable2StepStorage storage $) {\n        assembly {\n            $.slot := Ownable2StepStorageLocation\n        }\n    }\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    function __Ownable2Step_init() internal onlyInitializing {\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        Ownable2StepStorage storage $ = _getOwnable2StepStorage();\n        return $._pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        Ownable2StepStorage storage $ = _getOwnable2StepStorage();\n        $._pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        Ownable2StepStorage storage $ = _getOwnable2StepStorage();\n        delete $._pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        if (pendingOwner() != sender) {\n            revert OwnableUnauthorizedAccount(sender);\n        }\n        _transferOwnership(sender);\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/upgradeable/utils/PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\n    struct PausableStorage {\n        bool _paused;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\n\n    function _getPausableStorage() private pure returns (PausableStorage storage $) {\n        assembly {\n            $.slot := PausableStorageLocation\n        }\n    }\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        PausableStorage storage $ = _getPausableStorage();\n        return $._paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"contracts/wlfi/interfaces/IWorldLibertyFinancialRegistry.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.24;\n\n\ninterface IWorldLibertyFinancialRegistry {\n\n    // ==================================================\n    // ==================== Structs =====================\n    // ==================================================\n\n    /// @dev The entirety of this struct should compact down into one storage slot\n    struct LegacyUser {\n        /// @dev This is data type is big enough to fit the whole WLFI supply\n        uint112 amount;\n        /// @dev Incremental categories, where 0 represents NONE and should be considered unset\n        uint8 category;\n        /// @dev True if the user has \"activated\" their account by transferring their funds into the vester\n        bool isActivated;\n    }\n\n    struct RegistryStorage {\n        uint256 nonce;\n        mapping(address => LegacyUser) legacyUserMap;\n    }\n\n    // ==================================================\n    // ===================== Events =====================\n    // ==================================================\n\n    event NonceUpdated(uint256 nonce);\n    event LegacyUserUpdated(address indexed user, uint256 amount, uint8 category, bool isActivated);\n    event LegacyUserRemoved(address indexed user);\n    event LegacyUserTransferred(address indexed from, address indexed to);\n\n    // ==================================================\n    // ===================== Errors =====================\n    // ==================================================\n\n    error AlreadyInitialized(address user);\n    error AlreadyLegacyUser(address user);\n    error InvalidBulkInsertLegacyUserAtIndex(uint256 index);\n    error InvalidBulkInsertLegacyUserBalance(address user);\n    error InvalidBulkInsertLegacyUsersParams();\n    error InvalidNonce();\n    error InvalidUser(address user);\n    error Unauthorized();\n\n    // ==================================================\n    // ================== Initializers ==================\n    // ==================================================\n\n    function initialize() external;\n\n    // ===================================================\n    // =============== External Functions ================\n    // ===================================================\n\n    /**\n     * @notice  Allows the WLFI token to activate a legacy user. This is the typical flow most Legacy Users will follow\n     *          to initialize their vesting account.\n     *\n     * @param _user     The address of the user whose account will be activated\n     */\n    function wlfiActivateAccount(address _user) external;\n\n    /**\n     * @notice  Allows the WLFI token to reduce a user's allocation of locked tokens. Emits `LegacyUserUpdated`\n     *\n     * @param _user     The address of the user whose allocation will be reduced\n     * @param _amount   The amount to reduce the allocation by\n     */\n    function wlfiBurnAllocation(address _user, uint256 _amount) external;\n\n    /**\n     * @notice  Transfers the registration of `_from` account to the `_to` account. Reverts if `_to` is already\n     *          registered. `_to` account must be a fresh wallet. Reverts if `_from` is not a legacy user\n     *\n     * @param _from The from account whose registration is being transferred.\n     * @param _to   The to account whose registration is being received by `_from`.\n     */\n    function wlfiReallocateFrom(address _from, address _to) external;\n\n    /**\n     * @notice  Allows the WLFI token to change a user's vesting category. Emits `LegacyUserUpdated`\n     *\n     * @param _user     The user whose vesting category should change\n     * @param _category The user's new vesting category\n     */\n    function wlfiSetCategory(address _user, uint8 _category) external;\n\n    /**\n     * @notice  Allows the whitelist agent or owner to add Legacy Users to this registry. Each user is assigned an\n     *          amount of WLFI they have and a category. Categories are useful for partitioning users (between founders,\n     *          public sale recipient, OTC sale recipient, etc.). The lengths of these arrays must match and be > 0.\n     *\n     * @param _expectedNonce    The nonce that is expected be set in storage at the time of this call. Used for\n     *                          coordination with the offchain script.\n     * @param _users            The Legacy Users that will be added to the registry\n     * @param _amounts          The amount of WLFI that each Legacy User has. Must be equal to the Legacy User's balance\n     * @param _categories       The category in which each Legacy User resides\n     */\n    function agentBulkInsertLegacyUsers(\n        uint256 _expectedNonce,\n        address[] calldata _users,\n        uint256[] calldata _amounts,\n        uint8[] calldata _categories\n    ) external;\n\n    /**\n     * @notice  Allows the whitelist agent or owner to remove Legacy Users from this registry. The length of this array\n     *          must be > 0.\n     *\n     * @param _users            The Legacy Users that will be removed from the registry\n     */\n    function agentBulkRemoveLegacyUsers(\n        address[] calldata _users\n    ) external;\n\n    /**\n     *\n     * @return  The nonce of the latest insertion from calling {agentBulkInsertLegacyUsers}\n     */\n    function nonce() external view returns (uint256);\n\n    /**\n     *\n     * @param _user The user to check if they are considered a Legacy User or not\n     * @return  True if the user is considered a Legacy User or false otherwise\n     */\n    function isLegacyUser(address _user) external view returns (bool);\n\n    /**\n     *\n     * @param _user The user to check if they are considered a Legacy User and if their status is activated yet\n     * @return  True if the user is considered a Legacy User and they have been activated or false otherwise\n     */\n    function isLegacyUserAndIsActivated(address _user) external view returns (bool);\n\n    /**\n     *\n     * @param _user The user to check if they are considered a Legacy User and if their status is not activated yet\n     * @return  True if the user is considered a Legacy User and they have not been activated yet. False otherwise\n     */\n    function isLegacyUserAndIsNotActivated(address _user) external view returns (bool);\n\n    /**\n     *\n     * @param _user The user whose Legacy User info should be retrieved\n     * @return  The user's Legacy User info\n     */\n    function getLegacyUserInfo(address _user) external view returns (LegacyUser memory);\n\n    /**\n     *\n     * @param _user The user whose category should be retrieved\n     * @return  The user's assigned category\n     */\n    function getLegacyUserCategory(address _user) external view returns (uint8);\n\n    /**\n     *\n     * @param _user The user whose allocation should be retrieved\n     * @return  The user's assigned WLFI allocation\n     */\n    function getLegacyUserAllocation(address _user) external view returns (uint112);\n}\n"},{"file_path":"contracts/wlfi-staking/interfaces/IWLFIStaking.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.24;\n\nimport {IAccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol\";\nimport {IERC721Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\n\n/**\n * @title IWLFIStaking\n * @notice Interface for WLFI staking positions and ERC20 reward streams.\n * @dev `rewardTime` is the distribution timer. It runs at normal clock speed while someone is staking WLFI and\n *      pauses when nobody is staking. Values ending in `Scaled` use 1e36 fixed-point precision.\n */\ninterface IWLFIStaking is IAccessControlUpgradeable, IERC721Upgradeable {\n    // ==================================================\n    // ==================== Structs =====================\n    // ==================================================\n\n    /// @notice Parameters used to initialize a staking proxy.\n    struct InitializeParams {\n        /// @notice Account granted `DEFAULT_ADMIN_ROLE` and `REWARD_FUNDER_ROLE`.\n        address admin;\n        /// @notice Account granted `GUARDIAN_ROLE`.\n        address guardian;\n        /// @notice EOA that signs reward claim authorizations.\n        /// @dev Must have no code, so EOAs with an EIP-7702 delegation are rejected.\n        address rewardSigner;\n        /// @notice WLFI token address.\n        address wlfi;\n        /// @notice ERC721 name for staking positions.\n        string name;\n        /// @notice ERC721 symbol for staking positions.\n        string symbol;\n    }\n\n    /// @notice Principal and reward checkpoints for one staking position.\n    struct LockInfo {\n        /// @notice Staked WLFI, in 18-decimal base units.\n        uint128 amount;\n        /// @notice Staking period start timestamp, in seconds.\n        uint64 startTime;\n        /// @notice Earliest withdrawal and reward claim timestamp, in seconds.\n        uint64 unlockAvailableAt;\n        /// @notice Global time-over-stake integral when accrual began, scaled by 1e36.\n        uint256 startTimeIntegralScaled;\n        /// @notice Value of `rewardTime` when accrual began.\n        uint64 startRewardTime;\n    }\n\n    /// @notice Fixed-rate schedule for one reward deposit.\n    struct RewardStream {\n        /// @notice Stream budget, rounded down to whole token base units after a revision.\n        uint256 amount;\n        /// @notice Reward units released per second while someone is staking WLFI, scaled by 1e36.\n        uint256 rateScaled;\n        /// @notice Fractional remainder released at the stream end, scaled by 1e36.\n        uint256 endRemainderScaled;\n        /// @notice Value of `rewardTime` when release starts.\n        uint64 startRewardTime;\n        /// @notice Value of `rewardTime` when release ends.\n        uint64 endRewardTime;\n        /// @notice Distribution duration, in seconds.\n        /// @dev The funded duration is at least one day, rounded up to whole days, then extended to target\n        ///      00:00:00 UTC at creation. While nobody is staking WLFI, no rewards are released and completion is\n        ///      delayed.\n        uint64 releaseDuration;\n        /// @notice Whether an admin closed the stream early.\n        bool closed;\n        /// @notice Value of `rewardTime` when the stream closed, or zero while active.\n        uint64 closedRewardTime;\n        /// @notice Replacement stream ID, or zero if the stream was cancelled.\n        uint256 replacementStreamId;\n    }\n\n    /// @notice Current accounting for one reward token.\n    /// @dev With `P = 1e36`, `scheduledBalanceScaled` is derived as\n    ///      `totalFunded * P - totalReleasedScaled - totalRefunded * P - refundRemainderScaled`.\n    struct RewardTokenState {\n        /// @notice Number of active streams.\n        uint32 activeStreamCount;\n        /// @notice Number of streams created for this reward token.\n        uint64 streamCount;\n        /// @notice Number of distinct end times currently stored for active streams.\n        uint256 activeStreamEndTimeCount;\n        /// @notice Distribution seconds counted so far.\n        uint64 rewardTime;\n        /// @notice Next active stream end, or zero if none is active.\n        uint64 nextStreamEndRewardTime;\n        /// @notice Sum of active stream rates, scaled by 1e36.\n        uint256 currentCompositeRateScaled;\n        /// @notice Total funded, in token base units.\n        uint256 totalFunded;\n        /// @notice Total refunded, in token base units.\n        uint256 totalRefunded;\n        /// @notice Total released, rounded down to token base units.\n        uint256 totalReleased;\n        /// @notice Exact total released, scaled by 1e36.\n        uint256 totalReleasedScaled;\n        /// @notice Scheduled balance, rounded up to token base units.\n        uint256 scheduledBalance;\n        /// @notice Exact scheduled balance, scaled by 1e36.\n        uint256 scheduledBalanceScaled;\n        /// @notice Total paid to users, in token base units.\n        uint256 totalClaimed;\n        /// @notice Contract balance available for rewards, in token base units.\n        /// @dev When WLFI is the reward token, this excludes WLFI staked in active positions.\n        uint256 rewardBalance;\n        /// @notice Fractional cancellation remainder, scaled by 1e36.\n        uint256 refundRemainderScaled;\n    }\n\n    /// @notice Current global staking state and distribution timer.\n    struct GlobalRewardState {\n        /// @notice Distribution seconds counted so far.\n        uint64 rewardTime;\n        /// @notice Global time-over-stake integral, scaled by 1e36.\n        uint256 timeIntegralScaled;\n        /// @notice WLFI earning rewards, in 18-decimal base units.\n        uint256 totalActiveWlfi;\n    }\n\n    // ==================================================\n    // ===================== Events =====================\n    // ==================================================\n\n    /// @notice Emitted when a staking position is created.\n    /// @param owner Position owner.\n    /// @param lockId Position ID.\n    /// @param amount Staked WLFI, in 18-decimal base units.\n    /// @param startTime Creation timestamp, in seconds.\n    /// @param unlockAvailableAt Earliest withdrawal timestamp, in seconds.\n    event LockCreated(\n        address indexed owner, uint256 indexed lockId, uint256 amount, uint64 startTime, uint64 unlockAvailableAt\n    );\n\n    /// @notice Emitted when a position is unlocked.\n    /// @param owner Position owner.\n    /// @param lockId Position ID.\n    /// @param amount WLFI returned, in 18-decimal base units.\n    event LockUnlocked(address indexed owner, uint256 indexed lockId, uint256 amount);\n\n    /// @notice Emitted when a position restarts its staking period after claiming rewards.\n    /// @param owner Position owner.\n    /// @param lockId Position ID.\n    /// @param amount Restaked WLFI, in 18-decimal base units.\n    /// @param startTime New staking period start timestamp, in seconds.\n    /// @param unlockAvailableAt New earliest withdrawal timestamp, in seconds.\n    event LockRestaked(\n        address indexed owner, uint256 indexed lockId, uint256 amount, uint64 startTime, uint64 unlockAvailableAt\n    );\n\n    /// @notice Emitted when a position's unclaimed reward is forfeited to the remaining stakers on unlock.\n    /// @param owner Position owner.\n    /// @param lockId Position ID.\n    /// @param rewardToken Reward token.\n    /// @param amount Amount forfeited, in token base units.\n    event RewardForfeited(address indexed owner, uint256 indexed lockId, address indexed rewardToken, uint256 amount);\n\n    /// @notice Emitted when WLFI is added to an existing position.\n    /// @param owner Position owner.\n    /// @param lockId Position ID.\n    /// @param addedAmount WLFI added, in 18-decimal base units.\n    /// @param newAmount Position principal after the increase, in 18-decimal base units.\n    event LockAmountIncreased(\n        address indexed owner, uint256 indexed lockId, uint256 addedAmount, uint256 newAmount\n    );\n\n    /// @notice Emitted when a position's earliest withdrawal time is extended.\n    /// @param owner Position owner.\n    /// @param lockId Position ID.\n    /// @param amount Position principal, in 18-decimal base units.\n    /// @param previousUnlockAvailableAt Earliest withdrawal timestamp before the extension, in seconds.\n    /// @param unlockAvailableAt New earliest withdrawal timestamp, in seconds.\n    event LockExtended(\n        address indexed owner,\n        uint256 indexed lockId,\n        uint256 amount,\n        uint64 previousUnlockAvailableAt,\n        uint64 unlockAvailableAt\n    );\n\n    /// @notice Emitted when a reward token is registered.\n    /// @param rewardToken Reward token.\n    /// @param index Index in the reward token registry.\n    event RewardTokenAdded(address indexed rewardToken, uint256 indexed index);\n\n    /// @notice Emitted when an unused reward token is removed.\n    /// @param rewardToken Reward token.\n    /// @param index Former index in the reward token registry.\n    event RewardTokenRemoved(address indexed rewardToken, uint256 indexed index);\n\n    /// @notice Emitted when a reward stream is created.\n    /// @param funder Account that funded the stream.\n    /// @param rewardToken Reward token.\n    /// @param streamId Stream ID for this token.\n    /// @param amount Amount funded, in token base units.\n    /// @param releaseDuration Distribution duration, in seconds.\n    /// @param startRewardTime Value of `rewardTime` when release starts.\n    /// @param endRewardTime Value of `rewardTime` when release ends.\n    event RewardFunded(\n        address indexed funder,\n        address indexed rewardToken,\n        uint256 indexed streamId,\n        uint256 amount,\n        uint64 releaseDuration,\n        uint64 startRewardTime,\n        uint64 endRewardTime\n    );\n\n    /// @notice Emitted when a reward stream is revised.\n    /// @param admin Account that revised the stream.\n    /// @param rewardToken Reward token.\n    /// @param streamId Closed stream ID.\n    /// @param replacementStreamId Replacement stream ID, or zero after cancellation.\n    /// @param settledAmount Replacement stream's `amount`, or the refund paid after cancellation.\n    /// @param replacementDuration Replacement duration, or zero after cancellation.\n    /// @param closedRewardTime Value of `rewardTime` when the old stream closed.\n    /// @param newEndRewardTime Replacement end time, or zero after cancellation.\n    event RewardStreamRevised(\n        address indexed admin,\n        address indexed rewardToken,\n        uint256 indexed streamId,\n        uint256 replacementStreamId,\n        uint256 settledAmount,\n        uint64 replacementDuration,\n        uint64 closedRewardTime,\n        uint64 newEndRewardTime\n    );\n\n    /// @notice Emitted when all remaining streams sharing a reward-time endpoint settle.\n    /// @param rewardToken Reward token.\n    /// @param endRewardTime Value of `rewardTime` when the streams ended.\n    /// @param settledRewardTime Value of `rewardTime` when settlement was processed.\n    /// @param streamCount Number of streams settled at this endpoint.\n    /// @param rateDecreaseScaled Combined release rate removed, scaled by 1e36.\n    /// @param endRemainderScaled Combined fractional remainder released, scaled by 1e36.\n    event RewardStreamsSettled(\n        address indexed rewardToken,\n        uint64 indexed endRewardTime,\n        uint64 settledRewardTime,\n        uint32 streamCount,\n        uint256 rateDecreaseScaled,\n        uint256 endRemainderScaled\n    );\n\n    /// @notice Emitted for each position included in a reward claim.\n    /// @param owner Account receiving the reward.\n    /// @param lockId Position ID.\n    /// @param rewardToken Reward token.\n    /// @param amount Amount paid, in token base units.\n    event RewardClaimed(address indexed owner, uint256 indexed lockId, address indexed rewardToken, uint256 amount);\n\n    /// @notice Emitted when the reward signer or signer epoch changes.\n    /// @param rewardSigner New signer.\n    /// @param epoch New signer epoch.\n    event RewardSignerUpdated(address indexed rewardSigner, uint256 epoch);\n\n    // ==================================================\n    // ===================== Errors =====================\n    // ==================================================\n\n    error InvalidAdmin();\n    error InvalidGuardian();\n    error InvalidRewardSigner();\n    error InvalidToken();\n    error InvalidAmount();\n    error InvalidDuration();\n    error LockAlreadyExists();\n    error LockMatured();\n    error InvalidUnlockTimestamp();\n    error LockAmountTooLarge();\n    error TotalActiveWlfiTooLarge();\n    error RewardTokenAlreadyRegistered();\n    error RewardTokenNotRegistered();\n    error RewardTokenAlreadyFunded();\n    error RewardStreamNotFound();\n    error RewardStreamNotActive();\n    error TooManyRewardTokens();\n    error TooManyActiveStreamEndTimes();\n    error ScaledAmountTooLarge();\n    error NoLock();\n    error NotMatured();\n    error NoRewardsToClaim();\n    error ClaimAuthorizationExpired();\n    error ClaimAuthorizationNotYetValid();\n    error ClaimAuthorizationTooLong();\n    error InvalidClaimAuthorization();\n    error InsufficientRewardBalance();\n    error RewardAccountingMismatch();\n    error InsufficientPrincipalReserve();\n    error UnsupportedTokenBehavior();\n    error Soulbound();\n\n    // ==================================================\n    // =============== External Functions ===============\n    // ==================================================\n\n    /**\n     * @notice Initializes the staking proxy.\n     * @dev `rewardSigner` is an EOA. `name` and `symbol` are the ERC721 name and symbol.\n     * @param _params Roles, WLFI token, position metadata, and signer.\n     */\n    function initialize(InitializeParams calldata _params) external;\n\n    /**\n     * @notice Pauses new positions and reward streams.\n     * @dev `claimRewardsAndUnlockWlfi`, mature withdrawals, stream revisions, and views remain available.\n     *      `claimRewardsAndRestake`, principal additions, and lock extensions are paused.\n     */\n    function guardianPause() external;\n\n    /// @notice Resumes new positions and reward streams.\n    function adminUnpause() external;\n\n    /**\n     * @notice Sets the EOA that signs reward claim authorizations.\n     * @dev This also increments the signer epoch and invalidates earlier authorizations. The signer must have no\n     *      code, so EOAs with an EIP-7702 delegation are rejected.\n     * @param _rewardSigner New signer.\n     */\n    function adminSetRewardSigner(address _rewardSigner) external;\n\n    /**\n     * @notice Registers an ERC20 reward token.\n     * @dev Registration becomes permanent after the first reward funding. Reward tokens must be standard ERC20s.\n     *      The caller must hold and approve `_testAmount`, which is transferred in and returned during registration.\n     *      The transfer consumes allowance. This checks only the tested transfers; token behavior can change.\n     * @param _rewardToken Reward token address.\n     * @param _testAmount Nonzero amount to test in token base units, large enough to exercise any transfer fees.\n     */\n    function adminAddRewardToken(address _rewardToken, uint256 _testAmount) external;\n\n    /**\n     * @notice Removes a reward token that has never been funded.\n     * @dev Preserves the order of the remaining reward tokens and does not transfer token balances.\n     * @param _rewardToken Registered reward token.\n     */\n    function adminRemoveRewardToken(address _rewardToken) external;\n\n    /**\n     * @notice Deposits rewards and starts a fixed-rate stream.\n     * @dev Distribution starts immediately. If nobody is staking WLFI, no rewards are released and the remaining\n     *      duration stays the same. Heap slots are shared by identical reward-time endpoints, not calendar dates.\n     * @param _rewardToken Registered reward token.\n     * @param _amount Amount to deposit, in token base units.\n     * @param _releaseDuration Requested release duration, in seconds. Must be at least one day. The stored duration is\n     *      rounded up to whole days and extended to target 00:00:00 UTC at creation. Periods without stake delay\n     *      completion.\n     * @return streamId ID assigned to the stream for this token.\n     */\n    function funderCreateRewardStream(address _rewardToken, uint256 _amount, uint64 _releaseDuration)\n        external\n        returns (uint256 streamId);\n\n    /**\n     * @notice Closes a stream and either refunds or reschedules its unreleased rewards.\n     * @dev Released rewards stay with stakers. A zero duration refunds the unreleased balance to the caller. A\n     *      duration of at least one day starts a replacement stream immediately, using the same day-rounding rules as\n     *      `funderCreateRewardStream`.\n     * @param _rewardToken Registered reward token.\n     * @param _streamId Active stream ID for this token.\n     * @param _replacementDuration New release duration, or zero to cancel and refund. Nonzero values must be at least\n     *      one day.\n     * @return replacementStreamId New stream ID, or zero after cancellation.\n     * @return settledAmount Replacement stream's `amount`, or the refund paid after cancellation.\n     */\n    function adminReviseRewardStream(address _rewardToken, uint256 _streamId, uint64 _replacementDuration)\n        external\n        returns (uint256 replacementStreamId, uint256 settledAmount);\n\n    /**\n     * @notice Stakes WLFI and creates the caller's position.\n     * @dev Each account has one lock. The duration is the earliest withdrawal time. Rewards continue until the\n     *      position is unlocked. Contract callers must implement `IERC721Receiver.onERC721Received`.\n     * @param _amount WLFI to stake, in 18-decimal base units. Must be at least `MIN_LOCK_AMOUNT`.\n     * @param _duration Lock duration in seconds, from `MIN_LOCK_DURATION` through `MAX_LOCK_DURATION`.\n     * @return lockId ID of the new position.\n     */\n    function createLock(uint256 _amount, uint64 _duration) external returns (uint256 lockId);\n\n    /**\n     * @notice Adds WLFI to the caller's position before maturity.\n     * @dev Accrued rewards are snapshotted against the previous principal before the amount increases, so added tokens\n     *      earn from this transaction onward.\n     * @param _amount WLFI to add, in 18-decimal base units. Must be at least `MIN_LOCK_AMOUNT`.\n     */\n    function addToLock(uint256 _amount) external;\n\n    /**\n     * @notice Extends the caller's active position to a later withdrawal and reward claim timestamp.\n     * @dev `_newEndTimestamp` is later than the current `unlockAvailableAt`. Remaining lock from now is at most\n     *      `MAX_LOCK_DURATION`. If the position is already mature, remaining lock is at least `MIN_LOCK_DURATION`.\n     *      Already-accrued rewards cannot be claimed until the new timestamp. Rewards continue accruing.\n     * @param _newEndTimestamp New earliest withdrawal and reward claim timestamp, in seconds.\n     */\n    function extendLock(uint64 _newEndTimestamp) external;\n\n    /**\n     * @notice Unlocks the caller's mature position and returns its WLFI principal.\n     * @dev Unclaimed rewards are forfeited to the remaining stakers.\n     *      If none remain, the pool holds them for future stakes.\n     */\n    function unlock() external;\n\n    /**\n     * @notice Claims all reward tokens and restakes the principal for the chosen duration.\n     * @dev Rewards can be claimed at or after `unlockAvailableAt` while the lock is still open. Claims before maturity\n     *      revert with `NotMatured`. After unlock, claims revert with `NoLock` until a new lock matures. The EIP-712\n     *      authorization covers the caller, current lock ID, signer epoch, issue time, and deadline, and lasts at most\n     *      one day. The backend requires one vote for every completed 90 days actually staked. Reverts with\n     *      `NoRewardsToClaim` when every reward token pays zero, including when none is registered; use `extendLock`\n     *      to lengthen the lock instead.\n     * @param _duration New lock duration in seconds, from `MIN_LOCK_DURATION` through `MAX_LOCK_DURATION`.\n     * @param _issuedAt Authorization issue timestamp, in seconds.\n     * @param _deadline Authorization expiry timestamp, in seconds.\n     * @param _signature Signature from `rewardSigner()`.\n     * @return amounts Amount paid for each reward token, in `rewardTokens()` order.\n     */\n    function claimRewardsAndRestake(\n        uint64 _duration,\n        uint256 _issuedAt,\n        uint256 _deadline,\n        bytes calldata _signature\n    ) external returns (uint256[] memory amounts);\n\n    /**\n     * @notice Claims all reward tokens and returns the staked WLFI to the caller.\n     * @dev Requires the same staking period and authorization as `claimRewardsAndRestake`. Reverts with\n     *      `NoRewardsToClaim` when every reward token pays zero, including when none is registered; use `unlock`\n     *      to withdraw instead.\n     * @param _issuedAt Authorization issue timestamp, in seconds.\n     * @param _deadline Authorization expiry timestamp, in seconds.\n     * @param _signature Signature from `rewardSigner()`.\n     * @return amounts Amount paid for each reward token, in `rewardTokens()` order.\n     */\n    function claimRewardsAndUnlockWlfi(\n        uint256 _issuedAt,\n        uint256 _deadline,\n        bytes calldata _signature\n    ) external returns (uint256[] memory amounts);\n\n    // ==================================================\n    // ================= View Functions =================\n    // ==================================================\n\n    /// @notice Returns the account's lock ID, or zero if none exists.\n    /// @dev Unlock closes the position, so this returns zero until the account creates a new lock.\n    /// @param _account Account to query.\n    /// @return lockId Position ID, or zero if the account has no lock.\n    function lockIdOf(address _account) external view returns (uint256 lockId);\n\n    /// @notice Returns one position.\n    /// @param _lockId Position ID.\n    /// @return lockInfo Position data. A zero amount means the ID was never created or has been closed.\n    function locks(uint256 _lockId) external view returns (LockInfo memory lockInfo);\n\n    /// @notice Returns the number of staking positions.\n    /// @return count Current open staking positions.\n    function totalSupply() external view returns (uint256 count);\n\n    /// @notice Returns one position's unpaid reward through the current block.\n    /// @dev After unlock this is zero.\n    /// @param _rewardToken Registered reward token.\n    /// @param _lockId Position ID.\n    /// @return amount Unpaid reward, rounded down to token base units. A never-used ID returns zero.\n    function earned(address _rewardToken, uint256 _lockId) external view returns (uint256 amount);\n\n    /**\n     * @notice Returns estimated daily rewards for `_wlfiAmount`, or for `_account`'s current lock when it is zero.\n     * @dev Daily amounts are the current per-second release rate times 86,400 seconds, times `share / total`, rounded\n     *      down to token base units. `_wlfiAmount > 0` is a new stake of that size and dilutes `totalActiveWlfi`.\n     *      `_wlfiAmount == 0` uses `_account`'s lock and does not dilute. Ended streams are excluded.\n     * @param _account Account whose lock is used when `_wlfiAmount` is zero.\n     * @param _wlfiAmount Hypothetical new stake in 18-decimal WLFI base units, or zero to use `_account`'s lock.\n     * @return tokens Registered reward token addresses, in registry order.\n     * @return dailyAmounts Estimated token base units over 86,400 distribution seconds, aligned with `tokens`.\n     */\n    function previewRewards(address _account, uint256 _wlfiAmount)\n        external\n        view\n        returns (address[] memory tokens, uint256[] memory dailyAmounts);\n\n    /// @notice Returns the reward already paid for one position and token.\n    /// @param _rewardToken Reward token.\n    /// @param _lockId Position ID.\n    /// @return amount Reward paid, in token base units.\n    function claimedReward(address _rewardToken, uint256 _lockId) external view returns (uint256 amount);\n\n    /// @notice Returns current accounting for one reward token.\n    /// @param _rewardToken Registered reward token.\n    /// @return state Current token state.\n    function rewardState(address _rewardToken) external view returns (RewardTokenState memory state);\n\n    /// @notice Returns the current global staking state and distribution timer.\n    /// @return state Current global accounting preview.\n    function globalRewardState() external view returns (GlobalRewardState memory state);\n\n    /// @notice Returns one stored reward stream.\n    /// @param _rewardToken Registered reward token.\n    /// @param _streamId Stream ID for this token.\n    /// @return stream Stream data.\n    function rewardStream(address _rewardToken, uint256 _streamId) external view returns (RewardStream memory stream);\n\n    /// @notice Returns every registered reward token in registry order.\n    /// @return tokens Registered reward token addresses.\n    function rewardTokens() external view returns (address[] memory tokens);\n\n    /// @notice Returns the EOA authorized to sign reward claims.\n    /// @return signer Configured signer.\n    function rewardSigner() external view returns (address signer);\n\n    /// @notice Returns the signer epoch included in claim authorization digests.\n    /// @return epoch Current signer epoch.\n    function rewardSignerEpoch() external view returns (uint256 epoch);\n\n    /**\n     * @notice Returns the EIP-712 digest for a reward claim authorization.\n     * @dev The digest includes the current signer epoch and the account's current lock ID. Claim functions accept\n     *      authorizations lasting at most one day.\n     * @param _account Account authorized to claim.\n     * @param _issuedAt Authorization issue timestamp, in seconds.\n     * @param _deadline Authorization expiry timestamp, in seconds.\n     * @return digest EIP-712 digest.\n     */\n    function claimAuthorizationDigest(address _account, uint256 _issuedAt, uint256 _deadline)\n        external\n        view\n        returns (bytes32 digest);\n\n    /// @notice Returns the WLFI token.\n    /// @return token WLFI address.\n    function wlfi() external view returns (address token);\n\n    /// @notice Returns the WLFI owed to active positions and included in reward calculations.\n    /// @return amount Staked WLFI, in 18-decimal base units.\n    function totalActiveWlfi() external view returns (uint256 amount);\n\n    /// @notice Returns the role allowed to pause staking and funding.\n    /// @return role `keccak256(\"GUARDIAN_ROLE\")`.\n    function GUARDIAN_ROLE() external view returns (bytes32 role);\n\n    /// @notice Returns the role allowed to create streams.\n    /// @return role `keccak256(\"REWARD_FUNDER_ROLE\")`.\n    function REWARD_FUNDER_ROLE() external view returns (bytes32 role);\n\n    /// @notice Returns the minimum lock duration.\n    /// @return duration 180 days in seconds.\n    function MIN_LOCK_DURATION() external view returns (uint64 duration);\n\n    /// @notice Returns the maximum lock duration.\n    /// @return duration 1,460 days in seconds.\n    function MAX_LOCK_DURATION() external view returns (uint64 duration);\n\n    /// @notice Returns the minimum WLFI that can be staked or added in one transaction.\n    /// @return amount 0.01 WLFI, in 18-decimal base units.\n    function MIN_LOCK_AMOUNT() external view returns (uint256 amount);\n\n    /// @notice Returns the minimum reward stream duration.\n    /// @dev Requested durations target 00:00:00 UTC at creation. Periods without stake delay completion.\n    /// @return duration 1 day in seconds.\n    function MIN_REWARD_RELEASE_DURATION() external view returns (uint64 duration);\n\n    /// @notice Returns the reward token limit.\n    /// @return count Maximum registered reward tokens.\n    function MAX_REWARD_TOKENS() external view returns (uint256 count);\n\n    /// @notice Returns the active stream end-time limit per reward token.\n    /// @return count Maximum distinct active end times.\n    function MAX_ACTIVE_STREAM_END_TIMES() external view returns (uint256 count);\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/utils/cryptography/MessageHashUtils.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)\n\npragma solidity ^0.8.20;\n\nimport {Strings} from \"../Strings.sol\";\n\n/**\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\n *\n * The library provides methods for generating a hash of a message that conforms to the\n * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\n * specifications.\n */\nlibrary MessageHashUtils {\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing a bytes32 `messageHash` with\n     * `\"\\x19Ethereum Signed Message:\\n32\"` and hashing the result. It corresponds with the\n     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\n     * keccak256, although any bytes32 value can be safely used because the final digest will\n     * be re-hashed.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\") // 32 is the bytes-length of messageHash\n            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\n            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\n        }\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing an arbitrary `message` with\n     * `\"\\x19Ethereum Signed Message:\\n\" + len(message)` and hashing the result. It corresponds with the\n     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\n        return\n            keccak256(bytes.concat(\"\\x19Ethereum Signed Message:\\n\", bytes(Strings.toString(message.length)), message));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x00` (data with intended validator).\n     *\n     * The digest is calculated by prefixing an arbitrary `data` with `\"\\x19\\x00\"` and the intended\n     * `validator` address. Then hashing the result.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(hex\"19_00\", validator, data));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).\n     *\n     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\n     * `\\x19\\x01` and hashing the result. It corresponds to the hash signed by the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(ptr, hex\"19_01\")\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            digest := keccak256(ptr, 0x42)\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/oz-v5/immutable/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"uint256","name":"_tradingStartTimestamp","type":"uint256"},{"internalType":"address","name":"_registry","type":"address"},{"internalType":"address","name":"_vester","type":"address"},{"internalType":"address","name":"_wlfiStaking","type":"address"},{"internalType":"uint32","name":"_multiplierBps","type":"uint32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AccountNotActivated","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"Blacklisted","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"CannotReallocateToLegacyUser","type":"error"},{"inputs":[],"name":"CheckpointUnorderedInsertion","type":"error"},{"inputs":[],"name":"DeadlineExpired","type":"error"},{"inputs":[],"name":"DelegationMovedToSnapshot","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"uint256","name":"increasedSupply","type":"uint256"},{"internalType":"uint256","name":"cap","type":"uint256"}],"name":"ERC20ExceededSafeSupply","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"},{"internalType":"uint48","name":"clock","type":"uint48"}],"name":"ERC5805FutureLookup","type":"error"},{"inputs":[],"name":"ERC6372InconsistentClock","type":"error"},{"inputs":[],"name":"ElectionAlreadyPerformed","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"GuardianUnauthorizedAccount","type":"error"},{"inputs":[],"name":"InvalidAccount","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidAuthorizedSigner","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidMaxVotingPower","type":"error"},{"inputs":[],"name":"InvalidParameters","type":"error"},{"inputs":[],"name":"InvalidReallocation","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidStakingContract","type":"error"},{"inputs":[],"name":"InvalidStakingVotingMultiplier","type":"error"},{"inputs":[],"name":"InvalidValue","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[],"name":"NotImplemented","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"TeamElectionWouldBlackoutClaims","type":"error"},{"inputs":[],"name":"TransferNotAllowedYet","type":"error"},{"inputs":[{"internalType":"uint8","name":"category","type":"uint8"}],"name":"UnknownCategory","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"VesterNotInitialized","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"VoterIsExcluded","type":"error"},{"inputs":[{"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"VotesExpiredSignature","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotes","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"didTransferRegistry","type":"bool"}],"name":"Reallocated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isTransferAllowed","type":"bool"}],"name":"SetAllowListStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authorizedSigner","type":"address"}],"name":"SetAuthorizedSigner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isBlacklisted","type":"bool"}],"name":"SetBlacklistStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"guardian","type":"address"},{"indexed":false,"internalType":"bool","name":"isGuardian","type":"bool"}],"name":"SetGuardian","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxVotingPower","type":"uint256"}],"name":"SetMaxVotingPower","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"SetVotingPowerExcludedStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint8","name":"oldCategory","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"newCategory","type":"uint8"}],"name":"VestingUpdated","type":"event"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VOTING_POWER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REGISTRY","outputs":[{"internalType":"contract IWorldLibertyFinancialRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERMINAL_NON_RETAIL_CATEGORY","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERMINAL_RETAIL_CATEGORY","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRADING_START_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VESTER","outputs":[{"internalType":"contract IWorldLibertyFinancialVester","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WLFI_STAKING","outputs":[{"internalType":"contract IWLFIStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"activateAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"activateAccountAndClaimVest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authorizedSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32","name":"pos","type":"uint32"}],"name":"checkpoints","outputs":[{"components":[{"internalType":"uint48","name":"_key","type":"uint48"},{"internalType":"uint208","name":"_value","type":"uint208"}],"internalType":"struct Checkpoints.Checkpoint208","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimVest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"electVestingUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getAllowListStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getVotingPower","outputs":[{"internalType":"uint256","name":"votingPower","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardianPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_isBlacklisted","type":"bool"}],"name":"guardianSetBlacklistStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_authorizedSigner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isAfterTradingStartTimestamp","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"blacklistStatus","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"}],"name":"isGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_category","type":"uint8"}],"name":"isKnownNonRetailCategory","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isReadyToTransact","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isVoterExcluded","outputs":[{"internalType":"bool","name":"excludedStatus","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_bypassVester","type":"bool"}],"name":"ownerActivateAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_fromChunk","type":"address[]"},{"internalType":"address[]","name":"_toChunk","type":"address[]"},{"internalType":"uint256[]","name":"_valueChunk","type":"uint256[]"}],"name":"ownerBatchReallocateFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"ownerClaimVestFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_accounts","type":"address[]"}],"name":"ownerElectVestingUpdatesFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ownerPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"ownerReallocateFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"ownerRescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_authorizedSigner","type":"address"}],"name":"ownerSetAuthorizedSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_isBlacklisted","type":"bool"}],"name":"ownerSetBlacklistStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"ownerSetGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxVotingPower","type":"uint256"}],"name":"ownerSetMaxVotingPower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_isAllowed","type":"bool"}],"name":"ownerSetTransferBeforeStartStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"ownerSetVotingPowerExcludedStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ownerUnpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountWei","type":"uint256"}],"name":"previewLockVotingPower","outputs":[{"internalType":"uint256","name":"votingPower","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x0000000000000000000000000000000000000000000000000000000068b58ac00000000000000000000000004f61a99e42e21ea3c3eaf9b1b30fb80a7900d3ce00000000000000000000000074b4f6a2e579d730aacb9dd23cfbbaeb95029583000000000000000000000000196fee96efeaad585483a6d950e70286b68519230000000000000000000000000000000000000000000000000000000000002710"}