{"file_path":"src/WrappedMToken.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.26;\n\nimport { IndexingMath } from \"../lib/common/src/libs/IndexingMath.sol\";\nimport { UIntMath } from \"../lib/common/src/libs/UIntMath.sol\";\n\nimport { ForcedTransferable } from \"../lib/evm-m-extensions/src/components/forcedTransferable/ForcedTransferable.sol\";\nimport { Freezable } from \"../lib/evm-m-extensions/src/components/freezable/Freezable.sol\";\nimport { Pausable } from \"../lib/evm-m-extensions/src/components/pausable/Pausable.sol\";\n\nimport { IERC20 } from \"../lib/common/src/interfaces/IERC20.sol\";\n\nimport { ERC20Extended } from \"../lib/common/src/ERC20Extended.sol\";\nimport { Migratable } from \"../lib/common/src/Migratable.sol\";\n\nimport { IMTokenLike } from \"./interfaces/IMTokenLike.sol\";\nimport { IRegistrarLike } from \"./interfaces/IRegistrarLike.sol\";\nimport { ISwapFacilityLike } from \"./interfaces/ISwapFacilityLike.sol\";\nimport { IWrappedMToken } from \"./interfaces/IWrappedMToken.sol\";\n\n/*\n\n██╗    ██╗██████╗  █████╗ ██████╗ ██████╗ ███████╗██████╗     ███╗   ███╗    ████████╗ ██████╗ ██╗  ██╗███████╗███╗   ██╗\n██║    ██║██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗    ████╗ ████║    ╚══██╔══╝██╔═══██╗██║ ██╔╝██╔════╝████╗  ██║\n██║ █╗ ██║██████╔╝███████║██████╔╝██████╔╝█████╗  ██║  ██║    ██╔████╔██║       ██║   ██║   ██║█████╔╝ █████╗  ██╔██╗ ██║\n██║███╗██║██╔══██╗██╔══██║██╔═══╝ ██╔═══╝ ██╔══╝  ██║  ██║    ██║╚██╔╝██║       ██║   ██║   ██║██╔═██╗ ██╔══╝  ██║╚██╗██║\n╚███╔███╔╝██║  ██║██║  ██║██║     ██║     ███████╗██████╔╝    ██║ ╚═╝ ██║       ██║   ╚██████╔╝██║  ██╗███████╗██║ ╚████║\n ╚══╝╚══╝ ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝     ╚═╝     ╚══════╝╚═════╝     ╚═╝     ╚═╝       ╚═╝    ╚═════╝ ╚═╝  ╚═╝╚══════╝╚═╝  ╚═══╝\n\n*/\n\n/**\n * @title  ERC20 Token contract for wrapping M into a non-rebasing token with claimable yields.\n * @author M0 Labs\n */\ncontract WrappedMToken is IWrappedMToken, Migratable, ERC20Extended, Freezable, Pausable, ForcedTransferable {\n    /* ============ Structs ============ */\n\n    /**\n     * @dev   Struct to represent an account's balance and yield earning details.\n     * @param isEarning         Whether the account is actively earning yield.\n     * @param balance           The present amount of tokens held by the account.\n     * @param earningPrincipal  The earning principal for the account.\n     * @param hasClaimRecipient Whether the account has an explicitly set claim recipient.\n     */\n    struct Account {\n        // First Slot\n        bool isEarning;\n        uint240 balance;\n        // Second slot\n        uint112 earningPrincipal;\n        bool hasClaimRecipient;\n    }\n\n    /* ============ Variables ============ */\n\n    /// @inheritdoc IWrappedMToken\n    bytes32 public constant EARNERS_LIST_IGNORED_KEY = \"earners_list_ignored\";\n\n    /// @inheritdoc IWrappedMToken\n    bytes32 public constant EARNERS_LIST_NAME = \"earners\";\n\n    /// @inheritdoc IWrappedMToken\n    bytes32 public constant EXCESS_MANAGER_ROLE = keccak256(\"EXCESS_MANAGER_ROLE\");\n\n    /// @inheritdoc IWrappedMToken\n    bytes32 public constant CLAIM_OVERRIDE_RECIPIENT_KEY_PREFIX = \"wm_claim_override_recipient\";\n\n    /// @inheritdoc IWrappedMToken\n    bytes32 public constant MIGRATOR_KEY_PREFIX = \"wm_migrator_v2\";\n\n    /// @inheritdoc IWrappedMToken\n    address public immutable migrationAdmin;\n\n    /// @inheritdoc IWrappedMToken\n    address public immutable mToken;\n\n    /// @inheritdoc IWrappedMToken\n    address public immutable registrar;\n\n    /// @inheritdoc IWrappedMToken\n    address public immutable swapFacility;\n\n    /// @inheritdoc IWrappedMToken\n    uint112 public totalEarningPrincipal;\n\n    /// @inheritdoc IWrappedMToken\n    uint240 public totalEarningSupply;\n\n    /// @inheritdoc IWrappedMToken\n    uint240 public totalNonEarningSupply;\n\n    /// @dev Mapping of accounts to their respective `AccountInfo` structs.\n    mapping(address account => Account balance) internal _accounts;\n\n    /// @inheritdoc IWrappedMToken\n    uint128 public enableMIndex;\n\n    /// @inheritdoc IWrappedMToken\n    uint128 public disableIndex;\n\n    mapping(address account => address claimRecipient) internal _claimRecipients;\n\n    /// @inheritdoc IWrappedMToken\n    address public excessDestination;\n\n    /* ============ Modifiers ============ */\n\n    /// @dev Modifier to check if caller is SwapFacility.\n    modifier onlySwapFacility() {\n        if (msg.sender != swapFacility) revert NotSwapFacility();\n        _;\n    }\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @custom:oz-upgrades-unsafe-allow constructor\n     * @dev   Constructs the contract given an M Token address and migration admin.\n     *        Note that a proxy will not need to initialize since there are no mutable storage values affected.\n     * @param mToken_         The address of an M Token.\n     * @param registrar_      The address of a Registrar.\n     * @param swapFacility_   The address of a Swap Facility.\n     * @param migrationAdmin_ The address of a migration admin.\n     */\n    constructor(\n        address mToken_,\n        address registrar_,\n        address swapFacility_,\n        address migrationAdmin_\n    ) ERC20Extended(\"M (Wrapped) by M0\", \"wM\", 6) {\n        _disableInitializers();\n\n        if ((mToken = mToken_) == address(0)) revert ZeroMToken();\n        if ((registrar = registrar_) == address(0)) revert ZeroRegistrar();\n        if ((swapFacility = swapFacility_) == address(0)) revert ZeroSwapFacility();\n        if ((migrationAdmin = migrationAdmin_) == address(0)) revert ZeroMigrationAdmin();\n    }\n\n    /* ============ Initializer ============ */\n\n    /**\n     * @dev   Initializes the WrappedM token.\n     * @param admin_                 The address of an admin.\n     * @param freezeManager_         The address of a freeze manager.\n     * @param pauser_                The address of a pauser.\n     * @param forcedTransferManager_ The address of a forced transfer manager.\n     * @param excessManager_         The address of an excess manager.\n     * @param excessDestination_     The address of an excess destination.\n     */\n    function initialize(\n        address admin_,\n        address freezeManager_,\n        address pauser_,\n        address forcedTransferManager_,\n        address excessManager_,\n        address excessDestination_\n    ) public initializer {\n        __Context_init();\n        __ERC165_init();\n        __AccessControl_init();\n        __Pausable_init();\n\n        if (admin_ == address(0)) revert ZeroAdmin();\n        _grantRole(DEFAULT_ADMIN_ROLE, admin_);\n\n        if (excessManager_ == address(0)) revert ZeroExcessManager();\n        _grantRole(EXCESS_MANAGER_ROLE, excessManager_);\n\n        _setExcessDestination(excessDestination_);\n\n        __Freezable_init(freezeManager_);\n        __Pausable_init(pauser_);\n        __ForcedTransferable_init(forcedTransferManager_);\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IWrappedMToken\n    function wrap(address recipient_, uint256 amount_) external onlySwapFacility {\n        // NOTE: `msg.sender` is always SwapFacility contract.\n        //       `ISwapFacilityLike.msgSender()` is used to ensure that the original caller is passed to `_wrap`.\n        _wrap(ISwapFacilityLike(msg.sender).msgSender(), recipient_, UIntMath.safe240(amount_));\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function unwrap(address /* recipient_ */, uint256 amount_) external onlySwapFacility {\n        // NOTE: `msg.sender` is always SwapFacility contract.\n        //       `ISwapFacilityLike.msgSender()` is used to ensure that the original caller is passed to `_unwrap`.\n        // NOTE: `recipient` is not used in this function as the $M is always sent to SwapFacility contract.\n        _unwrap(ISwapFacilityLike(msg.sender).msgSender(), UIntMath.safe240(amount_));\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function claimFor(address account_) external returns (uint240 yield_) {\n        _requireNotPaused();\n        _revertIfFrozen(account_);\n\n        return _claim(account_, currentIndex(), false);\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function claimExcess() external returns (uint240 claimed_) {\n        _requireNotPaused();\n\n        int256 excess_ = excess();\n\n        if (excess_ <= 0) return 0;\n\n        emit ExcessClaimed(claimed_ = uint240(uint256(excess_)));\n\n        _mint(excessDestination, claimed_);\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function enableEarning() external {\n        _revertIfNotApprovedEarner(address(this));\n        if (isEarningEnabled()) revert EarningIsEnabled();\n\n        emit EarningEnabled(enableMIndex = _currentMIndex());\n\n        IMTokenLike(mToken).startEarning();\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function disableEarning() external {\n        _revertIfApprovedEarner(address(this));\n        if (!isEarningEnabled()) revert EarningIsDisabled();\n\n        emit EarningDisabled(disableIndex = currentIndex());\n\n        delete enableMIndex;\n\n        IMTokenLike(mToken).stopEarning();\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function startEarningFor(address account_) external {\n        if (!isEarningEnabled()) revert EarningIsDisabled();\n\n        _startEarningFor(account_, currentIndex());\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function startEarningFor(address[] calldata accounts_) external {\n        if (!isEarningEnabled()) revert EarningIsDisabled();\n\n        uint128 currentIndex_ = currentIndex();\n\n        for (uint256 index_; index_ < accounts_.length; ++index_) {\n            _startEarningFor(accounts_[index_], currentIndex_);\n        }\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function stopEarningFor(address account_) external {\n        _revertIfFrozen(account_);\n        _revertIfApprovedEarner(account_);\n\n        // NOTE: Skip routing yield to the claim recipient when paused or when that recipient is frozen, so an\n        //       earner cannot block their own deauthorization by pointing yield at a frozen recipient.\n        //       The yield stays on `account_` as balance, mirroring the freeze path in `_beforeFreeze`.\n        _stopEarningFor(account_, currentIndex(), paused() || isFrozen(claimRecipientFor(account_)));\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function stopEarningFor(address[] calldata accounts_) external {\n        uint128 currentIndex_ = currentIndex();\n        bool paused_ = paused();\n        FreezableStorageStruct storage $ = _getFreezableStorageLocation();\n\n        for (uint256 i; i < accounts_.length; ++i) {\n            _revertIfFrozen($, accounts_[i]);\n            _revertIfApprovedEarner(accounts_[i]);\n\n            _stopEarningFor(accounts_[i], currentIndex_, paused_ || isFrozen(claimRecipientFor(accounts_[i])));\n        }\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function setClaimRecipient(address claimRecipient_) external {\n        _accounts[msg.sender].hasClaimRecipient = (_claimRecipients[msg.sender] = claimRecipient_) != address(0);\n\n        emit ClaimRecipientSet(msg.sender, claimRecipient_);\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function setExcessDestination(address excessDestination_) external onlyRole(EXCESS_MANAGER_ROLE) {\n        _setExcessDestination(excessDestination_);\n    }\n\n    /* ============ Temporary Admin Migration ============ */\n\n    /// @inheritdoc IWrappedMToken\n    function migrate(address migrator_) external {\n        if (msg.sender != migrationAdmin) revert UnauthorizedMigration();\n\n        _migrate(migrator_);\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IWrappedMToken\n    function accruedYieldOf(address account_) public view returns (uint240 yield_) {\n        Account storage accountInfo_ = _accounts[account_];\n\n        return\n            accountInfo_.isEarning\n                ? _getAccruedYield(accountInfo_.balance, accountInfo_.earningPrincipal, currentIndex())\n                : 0;\n    }\n\n    /// @inheritdoc IERC20\n    function balanceOf(address account_) public view returns (uint256 balance_) {\n        return _accounts[account_].balance;\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function balanceWithYieldOf(address account_) external view returns (uint256 balance_) {\n        // NOTE: Claiming yield does not necessarily result in the account's new balance equaling the value returned by `balanceWithYieldOf`,\n        //       as the yield may be directed to a claim recipient different from the `account_`.\n        unchecked {\n            return balanceOf(account_) + accruedYieldOf(account_);\n        }\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function earningPrincipalOf(address account_) external view returns (uint112 earningPrincipal_) {\n        return _accounts[account_].earningPrincipal;\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function claimRecipientFor(address account_) public view returns (address recipient_) {\n        if (_accounts[account_].hasClaimRecipient) return _claimRecipients[account_];\n\n        address claimOverrideRecipient_ = address(\n            uint160(uint256(_getFromRegistrar(keccak256(abi.encode(CLAIM_OVERRIDE_RECIPIENT_KEY_PREFIX, account_)))))\n        );\n\n        return claimOverrideRecipient_ == address(0) ? account_ : claimOverrideRecipient_;\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function currentIndex() public view returns (uint128 index_) {\n        uint128 disableIndex_ = disableIndex == 0 ? IndexingMath.EXP_SCALED_ONE : disableIndex;\n\n        unchecked {\n            return\n                enableMIndex == 0\n                    ? disableIndex_\n                    : UIntMath.safe128((uint256(disableIndex_) * _currentMIndex()) / enableMIndex);\n        }\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function isEarning(address account_) external view returns (bool isEarning_) {\n        return _accounts[account_].isEarning;\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function isEarningEnabled() public view returns (bool isEnabled_) {\n        return enableMIndex != 0;\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function excess() public view returns (int256 excess_) {\n        unchecked {\n            uint256 earmarked_ = totalNonEarningSupply + projectedEarningSupply();\n            uint256 balance_ = _mBalanceOf(address(this));\n\n            return int256(balance_) - int256(earmarked_);\n        }\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function totalAccruedYield() external view returns (uint240 yield_) {\n        unchecked {\n            return projectedEarningSupply() - totalEarningSupply;\n        }\n    }\n\n    /// @inheritdoc IERC20\n    function totalSupply() external view returns (uint256 totalSupply_) {\n        unchecked {\n            return totalEarningSupply + totalNonEarningSupply;\n        }\n    }\n\n    /// @inheritdoc IWrappedMToken\n    function projectedEarningSupply() public view returns (uint240 supply_) {\n        return\n            UIntMath.max240(\n                IndexingMath.getPresentAmountRoundedUp(totalEarningPrincipal, currentIndex()),\n                totalEarningSupply\n            );\n    }\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @dev   Sets the excess destination to `excessDestination_`.\n     * @param excessDestination_ The address of the excess destination.\n     */\n    function _setExcessDestination(address excessDestination_) internal {\n        if (excessDestination_ == address(0)) revert ZeroExcessDestination();\n\n        emit ExcessDestinationSet(excessDestination = excessDestination_);\n    }\n\n    /**\n     * @dev Approve `spender_` to spend `amount_` of tokens from `account_`.\n     * @param  account_ The address approving the allowance.\n     * @param  spender_ The address approved to spend the tokens.\n     * @param  amount_  The amount of tokens being approved for spending.\n     */\n    function _approve(address account_, address spender_, uint256 amount_) internal override {\n        FreezableStorageStruct storage $ = _getFreezableStorageLocation();\n\n        _revertIfFrozen($, account_);\n        _revertIfFrozen($, spender_);\n\n        super._approve(account_, spender_, amount_);\n    }\n\n    /**\n     * @dev   Mints `amount_` tokens to `recipient_`.\n     * @param recipient_ The address whose account balance will be incremented.\n     * @param amount_    The present amount of tokens to mint.\n     */\n    function _mint(address recipient_, uint240 amount_) internal {\n        _revertIfInsufficientAmount(amount_);\n        _revertIfInvalidRecipient(recipient_);\n\n        _accounts[recipient_].isEarning\n            ? _addEarningAmount(recipient_, amount_, currentIndex())\n            : _addNonEarningAmount(recipient_, amount_);\n\n        emit Transfer(address(0), recipient_, amount_);\n    }\n\n    /**\n     * @dev   Burns `amount_` tokens from `account_`.\n     * @param account_ The address whose account balance will be decremented.\n     * @param amount_  The present amount of tokens to burn.\n     */\n    function _burn(address account_, uint240 amount_) internal {\n        _revertIfInsufficientAmount(amount_);\n\n        _accounts[account_].isEarning\n            ? _subtractEarningAmount(account_, amount_, currentIndex())\n            : _subtractNonEarningAmount(account_, amount_);\n\n        emit Transfer(account_, address(0), amount_);\n    }\n\n    /**\n     * @dev   Increments the token balance of `account_` by `amount_`, assuming non-earning status.\n     * @param account_ The address whose account balance will be incremented.\n     * @param amount_  The present amount of tokens to increment by.\n     */\n    function _addNonEarningAmount(address account_, uint240 amount_) internal {\n        // NOTE: Can be `unchecked` because the max amount of wrappable M is never greater than `type(uint240).max`.\n        unchecked {\n            _accounts[account_].balance += amount_;\n            totalNonEarningSupply += amount_;\n        }\n    }\n\n    /**\n     * @dev   Decrements the token balance of `account_` by `amount_`, assuming non-earning status.\n     * @param account_ The address whose account balance will be decremented.\n     * @param amount_  The present amount of tokens to decrement by.\n     */\n    function _subtractNonEarningAmount(address account_, uint240 amount_) internal {\n        Account storage accountInfo_ = _accounts[account_];\n        uint240 balance_ = accountInfo_.balance;\n\n        if (balance_ < amount_) revert InsufficientBalance(account_, balance_, amount_);\n\n        unchecked {\n            accountInfo_.balance = balance_ - amount_;\n            totalNonEarningSupply -= amount_;\n        }\n    }\n\n    /**\n     * @dev   Increments the token balance of `account_` by `amount_`, assuming earning status.\n     * @param account_      The address whose account balance will be incremented.\n     * @param amount_       The present amount of tokens to increment by.\n     * @param currentIndex_ The current index to use to compute the principal amount.\n     */\n    function _addEarningAmount(address account_, uint240 amount_, uint128 currentIndex_) internal {\n        Account storage accountInfo_ = _accounts[account_];\n\n        // NOTE: Tracks two principal amounts: rounded up and rounded down.\n        //       Slightly overestimates the principal of total earning supply to provide extra safety in `excess` calculations.\n        uint112 principalUp_ = IndexingMath.getPrincipalAmountRoundedUp(amount_, currentIndex_);\n        uint112 principalDown_ = IndexingMath.getPrincipalAmountRoundedDown(amount_, currentIndex_);\n\n        // NOTE: Can be `unchecked` because the max amount of wrappable M is never greater than `type(uint240).max`.\n        unchecked {\n            accountInfo_.balance += amount_;\n            accountInfo_.earningPrincipal = UIntMath.safe112(uint256(accountInfo_.earningPrincipal) + principalDown_);\n        }\n\n        _addTotalEarningSupply(amount_, principalUp_);\n    }\n\n    /**\n     * @dev   Decrements the token balance of `account_` by `amount_`, assuming earning status.\n     * @param account_      The address whose account balance will be decremented.\n     * @param amount_       The present amount of tokens to decrement by.\n     * @param currentIndex_ The current index to use to compute the principal amount.\n     */\n    function _subtractEarningAmount(address account_, uint240 amount_, uint128 currentIndex_) internal {\n        Account storage accountInfo_ = _accounts[account_];\n        uint240 balance_ = accountInfo_.balance;\n\n        if (balance_ < amount_) revert InsufficientBalance(account_, balance_, amount_);\n\n        uint112 earningPrincipal_ = accountInfo_.earningPrincipal;\n\n        // NOTE: Tracks two principal amounts: rounded up and rounded down.\n        //       Slightly overestimates the principal of total earning supply to provide extra safety in `excess` calculations.\n        uint112 principalUp_ = IndexingMath.getPrincipalAmountRoundedUp(amount_, currentIndex_);\n        uint112 principalDown_ = IndexingMath.getPrincipalAmountRoundedDown(amount_, currentIndex_);\n\n        unchecked {\n            accountInfo_.balance = balance_ - amount_;\n            // `min112` prevents `earningPrincipal` underflow.\n            accountInfo_.earningPrincipal = earningPrincipal_ - UIntMath.min112(principalUp_, earningPrincipal_);\n        }\n\n        _subtractTotalEarningSupply(amount_, principalDown_);\n    }\n\n    /**\n     * @dev    Claims accrued yield for `account_` given a `currentIndex_`.\n     * @param  account_      The address to claim accrued yield for.\n     * @param  currentIndex_ The current index to accrue until.\n     * @param  skipTransfer_ Whether to skip transferring yield to a non-self claim recipient.\n     * @return yield_        The accrued yield that was claimed.\n     */\n    function _claim(address account_, uint128 currentIndex_, bool skipTransfer_) internal returns (uint240 yield_) {\n        Account storage accountInfo_ = _accounts[account_];\n\n        if (!accountInfo_.isEarning) return 0;\n\n        uint240 startingBalance_ = accountInfo_.balance;\n\n        yield_ = _getAccruedYield(startingBalance_, accountInfo_.earningPrincipal, currentIndex_);\n\n        if (yield_ == 0) return 0;\n\n        unchecked {\n            // Update balance and total earning supply to account for the yield, but the principals have not changed.\n            accountInfo_.balance = startingBalance_ + yield_;\n            totalEarningSupply += yield_;\n        }\n\n        // When transferring is skipped, the yield stays on `account_`, so it is the effective recipient.\n        address claimRecipient_ = skipTransfer_ ? account_ : claimRecipientFor(account_);\n\n        // Emit the appropriate `Claimed` and `Transfer` events, depending on the claim override recipient\n        emit Claimed(account_, claimRecipient_, yield_);\n        emit Transfer(address(0), account_, yield_);\n\n        if (claimRecipient_ == account_) return yield_;\n\n        _transfer(account_, claimRecipient_, yield_, currentIndex_);\n    }\n\n    /**\n     * @dev   Transfers `amount_` tokens from `sender_` to `recipient_` given some current index.\n     * @param sender_       The sender's address.\n     * @param recipient_    The recipient's address.\n     * @param amount_       The amount to be transferred.\n     * @param currentIndex_ The current index.\n     */\n    function _transfer(address sender_, address recipient_, uint240 amount_, uint128 currentIndex_) internal {\n        _requireNotPaused();\n        _revertIfInvalidRecipient(recipient_);\n\n        FreezableStorageStruct storage $ = _getFreezableStorageLocation();\n\n        _revertIfFrozen($, msg.sender);\n        _revertIfFrozen($, sender_);\n        _revertIfFrozen($, recipient_);\n\n        emit Transfer(sender_, recipient_, amount_);\n\n        if (amount_ == 0) return;\n\n        Account storage senderInfo_ = _accounts[sender_];\n        Account storage recipientInfo_ = _accounts[recipient_];\n\n        bool senderIsEarner_ = senderInfo_.isEarning;\n        bool recipientIsEarner_ = recipientInfo_.isEarning;\n\n        // If sender and earner are different earner states, transfer affects total supplies.\n        if (senderIsEarner_ != recipientIsEarner_) {\n            senderIsEarner_\n                ? _subtractEarningAmount(sender_, amount_, currentIndex_)\n                : _subtractNonEarningAmount(sender_, amount_);\n\n            recipientIsEarner_\n                ? _addEarningAmount(recipient_, amount_, currentIndex_)\n                : _addNonEarningAmount(recipient_, amount_);\n\n            return;\n        }\n\n        if (senderInfo_.balance < amount_) revert InsufficientBalance(sender_, senderInfo_.balance, amount_);\n\n        // If sender and recipient are both earners or both non-earners, transfer does not affect total supplies.\n        senderIsEarner_\n            ? _transferBetweenEarners(senderInfo_, recipientInfo_, amount_, currentIndex_)\n            : _transferBetweenNonEarners(senderInfo_, recipientInfo_, amount_);\n    }\n\n    /**\n     * @dev   Internal ERC20 transfer function that needs to be implemented by the inheriting contract.\n     * @param sender_    The sender's address.\n     * @param recipient_ The recipient's address.\n     * @param amount_    The amount to be transferred.\n     */\n    function _transfer(address sender_, address recipient_, uint256 amount_) internal override {\n        _transfer(sender_, recipient_, UIntMath.safe240(amount_), currentIndex());\n    }\n\n    /**\n     * @dev   Transfers `amount_` tokens between earners given some current index.\n     * @param sender_       The sender's Account storage pointer.\n     * @param recipient_    The recipient's Account storage pointer.\n     * @param amount_       The amount to be transferred.\n     * @param currentIndex_ The current index.\n     */\n    function _transferBetweenEarners(\n        Account storage sender_,\n        Account storage recipient_,\n        uint240 amount_,\n        uint128 currentIndex_\n    ) internal {\n        uint112 earningPrincipal_ = sender_.earningPrincipal;\n\n        // `min112` prevents `earningPrincipal` underflow.\n        uint112 principal_ = UIntMath.min112(\n            IndexingMath.getPrincipalAmountRoundedUp(amount_, currentIndex_),\n            earningPrincipal_\n        );\n\n        // NOTE: Can be `unchecked` because `_transfer` already checked for insufficient sender balance.\n        unchecked {\n            sender_.balance -= amount_;\n            sender_.earningPrincipal = earningPrincipal_ - principal_;\n\n            recipient_.balance += amount_;\n            recipient_.earningPrincipal = UIntMath.safe112(uint256(recipient_.earningPrincipal) + principal_);\n        }\n    }\n\n    /**\n     * @dev   Transfers `amount_` tokens between non-earners.\n     * @param sender_    The sender's Account storage pointer.\n     * @param recipient_ The recipient's Account storage pointer.\n     * @param amount_    The amount to be transferred.\n     */\n    function _transferBetweenNonEarners(Account storage sender_, Account storage recipient_, uint240 amount_) internal {\n        // NOTE: Can be `unchecked` because `_transfer` already checked for insufficient sender balance.\n        unchecked {\n            sender_.balance -= amount_;\n            recipient_.balance += amount_;\n        }\n    }\n\n    /**\n     * @dev   Increments total earning supply by `amount_` tokens.\n     * @param amount_    The present amount of tokens to increment total earning supply by.\n     * @param principal_ The principal amount of tokens to increment total earning principal by.\n     */\n    function _addTotalEarningSupply(uint240 amount_, uint112 principal_) internal {\n        unchecked {\n            // Increment the total earning supply and principal proportionally.\n            totalEarningSupply += amount_;\n            totalEarningPrincipal = UIntMath.safe112(uint256(totalEarningPrincipal) + principal_);\n        }\n    }\n\n    /**\n     * @dev   Decrements total earning supply by `amount_` tokens.\n     * @param amount_    The present amount of tokens to decrement total earning supply by.\n     * @param principal_ The principal amount of tokens to decrement total earning principal by.\n     */\n    function _subtractTotalEarningSupply(uint240 amount_, uint112 principal_) internal {\n        uint240 totalEarningSupply_ = totalEarningSupply;\n        uint112 totalEarningPrincipal_ = totalEarningPrincipal;\n\n        unchecked {\n            // `min240` and `min112` prevent `totalEarningSupply` and `totalEarningPrincipal` underflow respectively.\n            totalEarningSupply = totalEarningSupply_ - UIntMath.min240(amount_, totalEarningSupply_);\n            totalEarningPrincipal = totalEarningPrincipal_ - UIntMath.min112(principal_, totalEarningPrincipal_);\n        }\n    }\n\n    /**\n     * @dev    Wraps `amount` M from `account_` into wM for `recipient`.\n     * @param  account_   The account depositing  M.\n     * @param  recipient_ The account receiving the minted wM.\n     * @param  amount_    The amount of M deposited.\n     */\n    function _wrap(address account_, address recipient_, uint240 amount_) internal {\n        _requireNotPaused();\n\n        FreezableStorageStruct storage $ = _getFreezableStorageLocation();\n\n        _revertIfFrozen($, account_);\n        _revertIfFrozen($, recipient_);\n\n        // NOTE: Always transfer from SwapFacility as it is the only contract that can call this function.\n        // NOTE: The behavior of `IMTokenLike.transferFrom` is known, so its return can be ignored.\n        IMTokenLike(mToken).transferFrom(msg.sender, address(this), amount_);\n\n        // NOTE: Mints precise amount of Wrapped $M to `recipient_`.\n        //       Option 1: $M transfer from an $M earner to another $M earner (`WrappedM` in earning state): rounds up → rounds up,\n        //                 0, 1, or XX extra wei may be locked in `WrappedM` compared to the minted amount of Wrapped $M.\n        //       Option 2: $M transfer from an $M non-earner to an $M earner (`WrappedM` in earning state): precise $M transfer → rounds down,\n        //                 0, -1, or -XX wei may be locked in `WrappedM` compared to the minted amount of Wrapped $M.\n        _mint(recipient_, amount_);\n    }\n\n    /**\n     * @dev    Unwraps `amount` wM from `account_` into M.\n     * @param  account_ The account whose wM is being burned.\n     * @param  amount_  The amount of wM burned.\n     */\n    function _unwrap(address account_, uint240 amount_) internal {\n        _requireNotPaused();\n\n        // NOTE: No recipient frozen check here. The final recipient receives $M (not Wrapped $M)\n        //       directly from SwapFacility, so a Wrapped $M frozen guard would have no effect.\n        _revertIfFrozen(account_);\n\n        // NOTE: Always burn from SwapFacility as it is the only contract that can call this function.\n        _burn(msg.sender, amount_);\n\n        // NOTE: The behavior of `IMTokenLike.transfer` is known, so its return can be ignored.\n        // NOTE: Computes the actual decrease in the $M balance of the `WrappedM` contract.\n        //       Option 1: $M transfer from an $M earner (`WrappedM` in earning state) to another $M earner: round up → rounds up.\n        //       Option 2: $M transfer from an $M earner (`WrappedM` in earning state) to an $M non-earner: round up → precise $M transfer.\n        //       In both cases, 0, 1, or XX extra wei may be deducted from the `WrappedM` contract's $M balance compared to the burned amount of Wrapped $M.\n        IMTokenLike(mToken).transfer(msg.sender, amount_);\n    }\n\n    /**\n     * @dev   Starts earning for `account` if allowed by the Registrar.\n     * @param account_      The account to start earning for.\n     * @param currentIndex_ The current index.\n     */\n    function _startEarningFor(address account_, uint128 currentIndex_) internal {\n        _requireNotPaused();\n        _revertIfFrozen(account_);\n        _revertIfNotApprovedEarner(account_);\n\n        Account storage accountInfo_ = _accounts[account_];\n\n        if (accountInfo_.isEarning) return;\n\n        uint240 balance_ = accountInfo_.balance;\n\n        // NOTE: Tracks two principal amounts: rounded up and rounded down.\n        //       Slightly overestimates the principal of total earning supply to provide extra safety in `excess` calculations.\n        uint112 principalUp_ = IndexingMath.getPrincipalAmountRoundedUp(balance_, currentIndex_);\n        uint112 principalDown_ = IndexingMath.getPrincipalAmountRoundedDown(balance_, currentIndex_);\n\n        accountInfo_.isEarning = true;\n        accountInfo_.earningPrincipal = principalDown_;\n\n        _addTotalEarningSupply(balance_, principalUp_);\n\n        unchecked {\n            totalNonEarningSupply -= balance_;\n        }\n\n        emit StartedEarning(account_);\n    }\n\n    /**\n     * @dev   Stops earning for `account` given some current index.\n     * @param account_      The account to stop earning for.\n     * @param currentIndex_ The current index.\n     * @param skipTransfer_ Whether to skip routing the claimed yield to a non-self claim recipient.\n     */\n    function _stopEarningFor(address account_, uint128 currentIndex_, bool skipTransfer_) internal {\n        Account storage accountInfo_ = _accounts[account_];\n\n        if (!accountInfo_.isEarning) return;\n\n        _claim(account_, currentIndex_, skipTransfer_);\n\n        uint240 balance_ = accountInfo_.balance;\n        uint112 earningPrincipal_ = accountInfo_.earningPrincipal;\n\n        delete accountInfo_.isEarning;\n        delete accountInfo_.earningPrincipal;\n\n        _subtractTotalEarningSupply(balance_, earningPrincipal_);\n\n        unchecked {\n            totalNonEarningSupply += balance_;\n        }\n\n        emit StoppedEarning(account_);\n    }\n\n    /**\n     * @dev   Hook called before freezing an account. Claims accrued yield and stops earning.\n     *        Routing to a claim recipient is skipped so freezing never reverts on a frozen\n     *        recipient and the yield stays on the frozen account, seizable via `forceTransfer`.\n     * @param account_ The account about to be frozen.\n     */\n    function _beforeFreeze(address account_) internal override {\n        _stopEarningFor(account_, currentIndex(), true);\n\n        super._beforeFreeze(account_);\n    }\n\n    /**\n     * @dev   Forcefully transfers `amount_` tokens from `frozenAccount_` to `recipient_`.\n     *        Bypasses pause (compliance > pause). Frozen account is guaranteed non-earning\n     *        thanks to `_beforeFreeze`.\n     * @param frozenAccount_ The frozen account from which tokens are seized.\n     * @param recipient_     The recipient's address.\n     * @param amount_        The amount to be transferred.\n     */\n    function _forceTransfer(address frozenAccount_, address recipient_, uint256 amount_) internal override {\n        _revertIfInvalidRecipient(recipient_);\n        _revertIfNotFrozen(frozenAccount_);\n        _revertIfFrozen(recipient_);\n\n        uint240 amount240_ = UIntMath.safe240(amount_);\n\n        emit Transfer(frozenAccount_, recipient_, amount240_);\n        emit ForcedTransfer(frozenAccount_, recipient_, msg.sender, amount240_);\n\n        if (amount240_ == 0) return;\n\n        _subtractNonEarningAmount(frozenAccount_, amount240_);\n\n        _accounts[recipient_].isEarning\n            ? _addEarningAmount(recipient_, amount240_, currentIndex())\n            : _addNonEarningAmount(recipient_, amount240_);\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /// @dev Returns the current index of the M Token.\n    function _currentMIndex() internal view returns (uint128 index_) {\n        return IMTokenLike(mToken).currentIndex();\n    }\n\n    /**\n     * @dev    Returns whether `account_` is a TTG-approved earner.\n     * @param  account_    The account being queried.\n     * @return isApproved_ True if the account_ is a TTG-approved earner, false otherwise.\n     */\n    function _isApprovedEarner(address account_) internal view returns (bool isApproved_) {\n        return\n            IRegistrarLike(registrar).get(EARNERS_LIST_IGNORED_KEY) != bytes32(0) ||\n            IRegistrarLike(registrar).listContains(EARNERS_LIST_NAME, account_);\n    }\n\n    /**\n     * @dev    Compute the yield given an account's balance, earning principal, and the current index.\n     * @param  balance_          The token balance of an earning account.\n     * @param  earningPrincipal_ The earning principal of the account.\n     * @param  currentIndex_     The current index.\n     * @return yield_            The yield accrued since the last interaction.\n     */\n    function _getAccruedYield(\n        uint240 balance_,\n        uint112 earningPrincipal_,\n        uint128 currentIndex_\n    ) internal pure returns (uint240 yield_) {\n        uint240 balanceWithYield_ = IndexingMath.getPresentAmountRoundedDown(earningPrincipal_, currentIndex_);\n\n        unchecked {\n            return (balanceWithYield_ <= balance_) ? 0 : balanceWithYield_ - balance_;\n        }\n    }\n\n    /**\n     * @dev    Retrieve a value from the Registrar.\n     * @param  key_   The key to retrieve the value for.\n     * @return value_ The value stored in the Registrar.\n     */\n    function _getFromRegistrar(bytes32 key_) internal view returns (bytes32 value_) {\n        return IRegistrarLike(registrar).get(key_);\n    }\n\n    /// @dev Returns the address of the contract to use as a migrator, if any.\n    function _getMigrator() internal view override returns (address migrator_) {\n        return\n            address(\n                uint160(\n                    // NOTE: A subsequent implementation should use a unique migrator prefix.\n                    uint256(_getFromRegistrar(keccak256(abi.encode(MIGRATOR_KEY_PREFIX, address(this)))))\n                )\n            );\n    }\n\n    /**\n     * @dev    Returns the M Token balance of `account_`.\n     * @param  account_ The account being queried.\n     * @return balance_ The M Token balance of the account.\n     */\n    function _mBalanceOf(address account_) internal view returns (uint240 balance_) {\n        // NOTE: M Token balance are limited to `uint240`.\n        return uint240(IMTokenLike(mToken).balanceOf(account_));\n    }\n\n    /**\n     * @dev   Reverts if `amount_` is equal to 0.\n     * @param amount_ Amount of token.\n     */\n    function _revertIfInsufficientAmount(uint256 amount_) internal pure {\n        if (amount_ == 0) revert InsufficientAmount(amount_);\n    }\n\n    /**\n     * @dev   Reverts if `account_` is address(0).\n     * @param account_ Address of an account.\n     */\n    function _revertIfInvalidRecipient(address account_) internal pure {\n        if (account_ == address(0)) revert InvalidRecipient(account_);\n    }\n\n    /**\n     * @dev   Reverts if `account_` is an approved earner.\n     * @param account_ Address of an account.\n     */\n    function _revertIfApprovedEarner(address account_) internal view {\n        if (_isApprovedEarner(account_)) revert IsApprovedEarner(account_);\n    }\n\n    /**\n     * @dev   Reverts if `account_` is not an approved earner.\n     * @param account_ Address of an account.\n     */\n    function _revertIfNotApprovedEarner(address account_) internal view {\n        if (!_isApprovedEarner(account_)) revert NotApprovedEarner(account_);\n    }\n}\n","deployed_bytecode":"0x608060405234801561000f575f80fd5b50600436106105c2575f3560e01c8063845828ad116102fc578063aae5e0c01161019d578063d505accf116100f3578063e3ee160e1161009e578063e94a010211610079578063e94a010214610f35578063e9ef148a14610f62578063ef55bec614610f75575f80fd5b8063e3ee160e14610eb1578063e583983614610ec4578063e63ab1e914610f0e575f80fd5b8063d9169487116100ce578063d916948714610e4d578063dd62ed3e14610e74578063ddeae03314610e9e575f80fd5b8063d505accf14610e14578063d547741f14610e27578063d7a49f0b14610e3a575f80fd5b8063c3b6f93911610153578063cc2a9a5b1161012e578063cc2a9a5b14610ddb578063ce5494bb14610dee578063cf09299514610e01575f80fd5b8063c3b6f93914610d90578063c9144ddb14610db7578063c967891a14610dd3575f80fd5b8063ae06b7e411610183578063ae06b7e414610d43578063b7b7289914610d6a578063bf376c7a14610d7d575f80fd5b8063aae5e0c014610d1d578063ace150a514610d30575f80fd5b80639a62984911610252578063a15e66bf11610208578063a8afc01f116101e3578063a8afc01f14610cef578063a9059cbb14610cf7578063aad1202914610d0a575f80fd5b8063a15e66bf14610c91578063a217fddf14610cb8578063a6378a2a14610cbf575f80fd5b80639fd5a6cf116102385780639fd5a6cf14610c44578063a08cb48b14610c57578063a0cc6a6814610c6a575f80fd5b80639a62984914610be25780639f3cbddf14610c09575f80fd5b80638d1fdf2f116102b257806391d148541161028d57806391d1485414610b7057806395d89b4114610bc7578063988cffc714610bcf575f80fd5b80638d1fdf2f14610b4d5780638d78bf7e14610b605780638fd3ab8014610b68575f80fd5b806384b0196e116102e257806384b0196e14610b0c57806388b7ab6314610b275780638a75f23814610b3a575f80fd5b8063845828ad14610ace57806384af270f14610ae1575f80fd5b80633644e515116104665780635a734520116103bc57806370a08231116103725780637ecebe001161034d5780637ecebe0014610a805780637f2eecc314610a9f5780638456cb5914610ac6575f80fd5b806370a0823114610a1057806374df255814610a4657806374edaa2014610a6d575f80fd5b80635c975abb116103a25780635c975abb146109ac5780635cf99384146109d657806363f15649146109e9575f80fd5b80635a7345201461095e5780635c60da1b14610985575f80fd5b806345c8b1a61161041c578063532992c5116103f7578063532992c51461093057806356d59ed2146109435780635a049a701461094b575f80fd5b806345c8b1a6146109025780634ebe94e314610915578063505136d51461091d575f80fd5b806337d45aa81161044c57806337d45aa8146108ae57806339f47693146108e75780633f4ba83a146108fa575f80fd5b80633644e5151461089357806336568abe1461089b575f80fd5b8063248a9ca31161051b5780632c786163116104d157806330adf81f116104ac57806330adf81f14610820578063313ce5671461084757806333bebb7714610880575f80fd5b80632c786163146107d35780632cfd442d146107e65780632f2ff15d1461080d575f80fd5b8063281b229d11610501578063281b229d146107565780632b20e397146107815780632b2134ea146107c0575f80fd5b8063248a9ca31461070d57806326987b601461074e575f80fd5b8063112baad71161057b57806318160ddd1161055657806318160ddd146106d75780631ae2379c146106f257806323b872dd146106fa575f80fd5b8063112baad714610688578063170e2070146106af578063174f6ce9146106c4575f80fd5b806306fdde03116105ab57806306fdde031461062b578063095ea7b3146106405780630a85ce8c14610653575f80fd5b806301ffc9a7146105c657806304dfd03d146105ee575b5f80fd5b6105d96105d436600461558f565b610f88565b60405190151581526020015b60405180910390f35b60075461060a906fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020016105e5565b610633611020565b6040516105e591906155fc565b6105d961064e366004615622565b611050565b61067a7f6561726e6572735f6c6973745f69676e6f72656400000000000000000000000081565b6040519081526020016105e5565b61067a7f776d5f6d69677261746f725f763200000000000000000000000000000000000081565b6106c26106bd36600461568d565b611065565b005b6106c26106d23660046156cc565b6110f9565b6005546004546001600160f01b03918216908216011661067a565b61067a611156565b6105d96107083660046156e7565b611192565b61067a61071b366004615725565b5f9081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b61060a61124c565b600554610769906001600160f01b031681565b6040516001600160f01b0390911681526020016105e5565b6107a87f000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c81565b6040516001600160a01b0390911681526020016105e5565b6107a86107ce3660046156cc565b611337565b6107696107e13660046156cc565b61140c565b61067a7fc66b3536568140ce119bcc21a4fa7e3449a56fb5f260d32ff8e719230264132c81565b6106c261081b36600461573c565b611469565b61067a7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61086e7f000000000000000000000000000000000000000000000000000000000000000681565b60405160ff90911681526020016105e5565b6106c261088e3660046156e7565b6114b2565b61067a6114e7565b6106c26108a936600461573c565b611570565b6003546108c8906dffffffffffffffffffffffffffff1681565b6040516dffffffffffffffffffffffffffff90911681526020016105e5565b6106c26108f5366004615622565b6115c1565b6106c2611698565b6106c26109103660046156cc565b6116ca565b61076961171e565b6106c261092b3660046156cc565b611759565b6106c261093e36600461576a565b61178c565b6107696117ab565b6106c26109593660046157b2565b6117c7565b61067a7f6561726e6572730000000000000000000000000000000000000000000000000081565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546107a8565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff166105d9565b61067a6109e43660046156cc565b6117e7565b61067a7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b3581565b61067a610a1e3660046156cc565b6001600160a01b03165f9081526006602052604090205461010090046001600160f01b031690565b6107a87f000000000000000000000000f7298f047f92d0eb21231478ef6ba9fe1ecd4c7381565b6106c2610a7b3660046156cc565b61182e565b61067a610a8e3660046156cc565b5f6020819052908152604090205481565b61067a7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6106c261188a565b6106c2610adc3660046156cc565b6118bc565b6105d9610aef3660046156cc565b6001600160a01b03165f9081526006602052604090205460ff1690565b610b14611971565b6040516105e597969594939291906157fe565b6106c2610b35366004615950565b611a19565b600454610769906001600160f01b031681565b6106c2610b5b3660046156cc565b611a48565b610769611a9c565b6106c2611b19565b6105d9610b7e36600461573c565b5f9182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610633611b2b565b6106c2610bdd36600461568d565b611b56565b61067a7f29d497e50c7b1bb72d16f5c1dc421a733085f4402f4a65adbb02a4cdc824b0ad81565b6108c8610c173660046156cc565b6001600160a01b03165f908152600660205260409020600101546dffffffffffffffffffffffffffff1690565b6106c2610c523660046159d3565b611bee565b6106c2610c65366004615a44565b611bfe565b61067a7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b61067a7f776d5f636c61696d5f6f766572726964655f726563697069656e74000000000081565b61067a5f81565b60075461060a9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6106c2611c28565b6105d9610d05366004615622565b611d74565b6106c2610d1836600461568d565b611d80565b6106c2610d2b36600461568d565b611e0d565b6106c2610d3e366004615a44565b611f3f565b6107a87f000000000000000000000000b6807116b3b1b321a390594e31ecd6e0076f627881565b6106c2610d78366004615aaa565b611f5f565b6106c2610d8b366004615622565b611f77565b6107a87f000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b81565b6007546fffffffffffffffffffffffffffffffff1615156105d9565b6106c261204b565b6106c2610de9366004615aff565b612172565b6106c2610dfc3660046156cc565b6123d0565b6106c2610e0f366004615950565b61243b565b6106c2610e22366004615b7d565b61245b565b6106c2610e3536600461573c565b61246b565b6106c2610e48366004615be7565b6124ae565b61067a7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b61067a610e82366004615c86565b600260209081525f928352604080842090915290825290205481565b610769610eac3660046156cc565b6125ab565b6106c2610ebf366004615cb2565b6125cf565b6105d9610ed23660046156cc565b6001600160a01b03165f9081527f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00602052604090205460ff1690565b61067a7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6105d9610f43366004615622565b600160209081525f928352604080842090915290825290205460ff1681565b6009546107a8906001600160a01b031681565b6106c2610f83366004615cb2565b6125ef565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061101a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b606061104b7f4d20285772617070656429206279204d3000000000000000000000000000000061260f565b905090565b5f61105c338484612700565b50600192915050565b7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b3561108f81612740565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce005f5b838110156110f2576110ea828686848181106110d0576110d0615d31565b90506020020160208101906110e591906156cc565b61274a565b6001016110b2565b5050505050565b611102816127c3565b61110b8161283f565b6111538161111761124c565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff168061114e575061114e610ed285611337565b61288a565b50565b5f8061116061171e565b6005546001600160f01b03908116919091011690505f61117f3061297e565b6001600160f01b03169190910392915050565b6001600160a01b0383165f9081526002602090815260408083203384529091528120545f198114611234578281101561120c576040517f192b9e4e00000000000000000000000000000000000000000000000000000000815233600482015260248101829052604481018490526064015b60405180910390fd5b6001600160a01b0385165f908152600260209081526040808320338452909152902083820390555b61123f858585612a24565b60019150505b9392505050565b6007545f90819070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16156112ac5760075470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166112b3565b64e8d4a510005b6007549091506fffffffffffffffffffffffffffffffff161561132f5760075461132a906fffffffffffffffffffffffffffffffff166112f1612a3f565b6fffffffffffffffffffffffffffffffff16836fffffffffffffffffffffffffffffffff16028161132457611324615d45565b04612ac0565b611331565b805b91505090565b6001600160a01b0381165f908152600660205260408120600101546e010000000000000000000000000000900460ff161561138a57506001600160a01b039081165f908152600860205260409020541690565b5f6113ee7f776d5f636c61696d5f6f766572726964655f726563697069656e740000000000846040516020016113d39291909182526001600160a01b0316602082015260400190565b60405160208183030381529060405280519060200120612b0b565b90506001600160a01b038116156114055780611245565b5090919050565b6001600160a01b0381165f908152600660205260408120805460ff16611432575f611245565b805460018201546112459161010090046001600160f01b0316906dffffffffffffffffffffffffffff1661146461124c565b612b73565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546114a281612740565b6114ac8383612bae565b50505050565b7fc66b3536568140ce119bcc21a4fa7e3449a56fb5f260d32ff8e719230264132c6114dc81612740565b6114ac848484612c7a565b5f306001600160a01b037f0000000000000000000000006d9db63afccf515f393d5e65be69d38bb3b29d131614801561153f57507f000000000000000000000000000000000000000000000000000000000000000146145b61154b5761104b612e20565b507f6d63411115eeb569a86988e208833d90afbf034c3bd6c6ef5fc08edaf5e8085d90565b6001600160a01b03811633146115b2576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115bc8282612ed5565b505050565b336001600160a01b037f000000000000000000000000b6807116b3b1b321a390594e31ecd6e0076f62781614611623576040517f2bfe1b5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611694336001600160a01b031663d737d0c76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611662573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116869190615d59565b61168f83612f79565b612fbb565b5050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6116c281612740565b611153613085565b7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b356116f481612740565b6116947f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce008361274a565b6003545f9061104b90611748906dffffffffffffffffffffffffffff1661174361124c565b6130f7565b6004546001600160f01b0316613102565b7f29d497e50c7b1bb72d16f5c1dc421a733085f4402f4a65adbb02a4cdc824b0ad61178381612740565b61169482613122565b6117a18461179a86866131c3565b848461322a565b6114ac848461323e565b6004545f906001600160f01b03166117c161171e565b03905090565b6117dd856117d587876131c3565b8585856132a2565b6110f2858561323e565b5f6117f18261140c565b6001600160f01b0316611827836001600160a01b03165f908152600660205260409020546001600160f01b036101009091041690565b0192915050565b6007546fffffffffffffffffffffffffffffffff16611879576040517fb019ea3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111538161188561124c565b6132b2565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6118b481612740565b6111536133d2565b335f81815260086020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038716908117909155600690925280832060010180547fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff168315156e01000000000000000000000000000002179055519092917f7df311a62f64e432c64a6003630264209cb8dd81c3d59d93031f8e8e72f0657c91a350565b5f6060805f805f60606119a37f4d20285772617070656429206279204d3000000000000000000000000000000061260f565b604080515f8082526060820183526001602083019081527f3100000000000000000000000000000000000000000000000000000000000000938301939093527f0f000000000000000000000000000000000000000000000000000000000000009b939a5091985046975030965090945092509050565b611a3187611a2b89898989898961342d565b836134a7565b611a3f8787878787876134f2565b50505050505050565b7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b35611a7281612740565b6116947f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce0083613553565b5f611aa56135d4565b5f611aae611156565b90505f8113611abe575f91505090565b6040516001600160f01b038216815290915081907f49ec4048a361156a5338ff734a59a750f44cb5753bbe0886c6f39289bec2a0149060200160405180910390a1600954611b15906001600160a01b031683613630565b5090565b611b29611b24613758565b61379d565b565b606061104b7f774d00000000000000000000000000000000000000000000000000000000000061260f565b6007546fffffffffffffffffffffffffffffffff16611ba1576040517fb019ea3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611baa61124c565b90505f5b828110156114ac57611be6848483818110611bcb57611bcb615d31565b9050602002016020810190611be091906156cc565b836132b2565b600101611bae565b6110f285611a2b8787878761397f565b611c108861179a8a8a8a8a8a8a61342d565b611c1e8888888888886134f2565b5050505050505050565b611c313061283f565b6007546fffffffffffffffffffffffffffffffff16611c7c576040517fb019ea3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fee580fdb4da10ea17aa673e6f5c8c2370b4166d6a94bc88900e5a96d0589e3ce611ca561124c565b600780546fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009390911692830217905560405190815260200160405180910390a160075f6101000a8154906fffffffffffffffffffffffffffffffff02191690557f000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b6001600160a01b0316639f8495f96040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611d62575f80fd5b505af11580156114ac573d5f803e3d5ffd5b5f61105c338484612a24565b7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b35611daa81612740565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce005f5b838110156110f257611e0582868684818110611deb57611deb615d31565b9050602002016020810190611e0091906156cc565b613553565b600101611dcd565b5f611e1661124c565b90505f611e447fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1690565b90507f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce005f5b84811015611f3757611ea182878784818110611e8757611e87615d31565b9050602002016020810190611e9c91906156cc565b613a12565b611ed0868683818110611eb657611eb6615d31565b9050602002016020810190611ecb91906156cc565b61283f565b611f2f868683818110611ee557611ee5615d31565b9050602002016020810190611efa91906156cc565b85858061114e575061114e610ed28a8a87818110611f1a57611f1a615d31565b90506020020160208101906107ce91906156cc565b600101611e69565b505050505050565b611f518861179a8a8a8a8a8a8a613a6f565b611c1e888888888888613ade565b611f6d83611a2b85856131c3565b6115bc838361323e565b336001600160a01b037f000000000000000000000000b6807116b3b1b321a390594e31ecd6e0076f62781614611fd9576040517f2bfe1b5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611694336001600160a01b031663d737d0c76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612018573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061203c9190615d59565b8361204684612f79565b613bcd565b61205430613cca565b6007546fffffffffffffffffffffffffffffffff16156120a0576040517f7a42736800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f5098de6eb11dbd1127cf4dcd5e960e3944d48a7570b9b1939cff715cb35c5a186120c9612a3f565b600780547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff92909216918217905560405190815260200160405180910390a17f000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b6001600160a01b031663a36e40fc6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611d62575f80fd5b5f61217b613d14565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156121a75750825b90505f8267ffffffffffffffff1660011480156121c35750303b155b9050811580156121d1575080155b15612208576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156122695784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b612271613d3c565b612279613d3c565b612281613d3c565b612289613d3c565b6001600160a01b038b166122c9576040517f7289db0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122d35f8c612bae565b506001600160a01b038716612313576040517ede954c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61233d7f29d497e50c7b1bb72d16f5c1dc421a733085f4402f4a65adbb02a4cdc824b0ad88612bae565b5061234786613122565b6123508a613d44565b61235989613db6565b61236288613e28565b83156123c35784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b336001600160a01b037f000000000000000000000000f7298f047f92d0eb21231478ef6ba9fe1ecd4c731614612432576040517f51e2625e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111538161379d565b61244d87611a2b898989898989613a6f565b611a3f878787878787613ade565b611a3f876117d58989898961397f565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546124a481612740565b6114ac8383612ed5565b7fc66b3536568140ce119bcc21a4fa7e3449a56fb5f260d32ff8e719230264132c6124d881612740565b8584811415806124e85750808314155b1561251f576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b818110156125a05761259889898381811061253e5761253e615d31565b905060200201602081019061255391906156cc565b88888481811061256557612565615d31565b905060200201602081019061257a91906156cc565b87878581811061258c5761258c615d31565b90506020020135612c7a565b600101612521565b505050505050505050565b5f6125b46135d4565b6125bd826127c3565b61101a826125c961124c565b5f613e9a565b6125e1896117d58b8b8b8b8b8b613a6f565b6125a0898989898989613ade565b612601896117d58b8b8b8b8b8b61342d565b6125a08989898989896134f2565b60605f5b602081108015612634575082816020811061263057612630615d31565b1a15155b156126495761264281615d74565b9050612613565b5f8167ffffffffffffffff811115612663576126636158b0565b6040519080825280601f01601f19166020018201604052801561268d576020820181803683370190505b5090505f5b828110156126f8578481602081106126ac576126ac615d31565b1a60f81b8282815181106126c2576126c2615d31565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600101612692565b509392505050565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce0061272b8185613a12565b6127358184613a12565b6114ac84848461406a565b61115381336140ca565b6001600160a01b0381165f9081526020839052604090205460ff1661276d575050565b6001600160a01b0381165f8181526020848152604091829020805460ff1916905590514281527f07d647ad688e085159820c1d8d030e5765cdc5274d4ee4065c6066b388a2ef5991015b60405180910390a25050565b6001600160a01b0381165f9081527f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00602052604090205460ff1615611153576040517f4f2a367e0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b61284881614156565b15611153576040517f577be7470000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b6001600160a01b0383165f908152600660205260409020805460ff166128b05750505050565b6128bb848484613e9a565b50805460018201805460ff19831684556dffffffffffffffffffffffffffff1981169091556101009091046001600160f01b0316906dffffffffffffffffffffffffffff1661290a82826142e8565b600580546001600160f01b038082168501167fffff0000000000000000000000000000000000000000000000000000000000009091161790556040516001600160a01b038716907f9467bac89b535c15fcd73b0e7b12e123a045fd17124952dfa868dfdf5e42d48d905f90a2505050505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301525f917f000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b909116906370a08231906024015b602060405180830381865afa158015612a00573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101a9190615d98565b6115bc8383612a3284612f79565b612a3a61124c565b614387565b5f7f000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b6001600160a01b03166326987b606040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a9c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104b9190615daf565b5f6fffffffffffffffffffffffffffffffff821115611b15576040517fec5d4e2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f8eaa6ac0000000000000000000000000000000000000000000000000000000008152600481018290525f907f000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c6001600160a01b031690638eaa6ac0906024016129e5565b5f80612b7f8484614619565b9050846001600160f01b0316816001600160f01b03161115612ba357848103612ba5565b5f5b95945050505050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff16612c71575f848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055612c273390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505061101a565b5f91505061101a565b612c8382614624565b612c8c8361466f565b612c95826127c3565b5f612c9f82612f79565b6040516001600160f01b03821681529091506001600160a01b0380851691908616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36040516001600160f01b038216815233906001600160a01b0385811691908716907f47cea260e2dfb95ed2ab59ad44fe2ac9cddb432afb828d2a1475936b5a2b829a9060200160405180910390a4806001600160f01b03165f03612d525750505050565b612d5c84826146ea565b6001600160a01b0383165f9081526006602052604090205460ff16612e0e576001600160a01b0383165f90815260066020526040902080547fff000000000000000000000000000000000000000000000000000000000000ff8116610100918290046001600160f01b039081168501811690920217909155600580547fffff000000000000000000000000000000000000000000000000000000000000811690831684019092169190911790556114ac565b6114ac8382612e1b61124c565b6147e8565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f612e6b7f4d20285772617070656429206279204d3000000000000000000000000000000061260f565b80516020918201206040805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff1615612c71575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505061101a565b5f6001600160f01b03821115611b15576040517f2a49c10d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fc36135d4565b612fcc826127c3565b612fd633826148b7565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526001600160f01b03821660248201527f000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b6001600160a01b03169063a9059cbb906044016020604051808303815f875af1158015613061573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115bc9190615dde565b61308d61494f565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a150565b5f61124583836149aa565b5f816001600160f01b0316836001600160f01b0316116114055781611245565b6001600160a01b038116613162576040517fc956307100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600980547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f1d7885f1e23525b16c7af644a56936bace8ab48fca508909d54b9bc86186ca37905f90a250565b604080517f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960208201526001600160a01b03841691810191909152606081018290525f90611245906080015b604051602081830303815290604052805190602001206149e6565b6114ac61323985858585614a47565b614a82565b6132488282614c46565b6001600160a01b0382165f818152600160208181526040808420868552909152808320805460ff1916909217909155518392917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a35050565b6110f26132398686868686614cb5565b6132ba6135d4565b6132c3826127c3565b6132cc82613cca565b6001600160a01b0382165f908152600660205260409020805460ff16156132f257505050565b805461010090046001600160f01b03165f61330d8285614cfd565b90505f61331a8386614d08565b8454600160ff1990911681178655850180546dffffffffffffffffffffffffffff19166dffffffffffffffffffffffffffff8316179055905061335d8383614d13565b600580546001600160f01b03808216869003167fffff0000000000000000000000000000000000000000000000000000000000009091161790556040516001600160a01b038716907f8fbc5add0c3fc76c7a869df537ee9250843681f6bbc2ea9735d40c6dc259414c905f90a2505050505050565b6133da6135d4565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336130d9565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208201526001600160a01b038089169282019290925290861660608201526080810185905260a0810184905260c0810183905260e081018290525f9061349c906101000161320f565b979650505050505050565b5f6134b3848484614da0565b90505f8160058111156134c8576134c8615dfd565b036134d35750505050565b6134de848484614de4565b156134e95750505050565b6114ac81614a82565b336001600160a01b03861614613545576040517f1c5939f30000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0386166024820152604401611203565b611f37868686868686613ade565b6001600160a01b0381165f9081526020839052604090205460ff1615613577575050565b61358081614f01565b6001600160a01b0381165f8181526020849052604090819020805460ff19166001179055517f68e0d8c112165d0949ce87205b719ed7d98c7401866c34a159f7c67c6f5620e7906127b79042815260200190565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1615611b29576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613642816001600160f01b0316614f14565b61364b82614624565b6001600160a01b0382165f9081526006602052604090205460ff166136fd576001600160a01b0382165f90815260066020526040902080547fff000000000000000000000000000000000000000000000000000000000000ff8116610100918290046001600160f01b039081168501811690920217909155600580547fffff0000000000000000000000000000000000000000000000000000000000008116908316840190921691909117905561370a565b61370a8282612e1b61124c565b6040516001600160f01b03821681526001600160a01b038316905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b604080517f776d5f6d69677261746f725f7632000000000000000000000000000000000000602082015230918101919091525f90613798906060016113d3565b919050565b6001600160a01b0381166137dd576040517f0d626a3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b5f03613820576040517f8d1e7cf400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6138497f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b90505f826001600160a01b03166040515f60405180830381855af49150503d805f8114613891576040519150601f19603f3d011682016040523d82523d5f602084013e613896565b606091505b50509050806138d1576040517fa27bfda200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6138fa7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050806001600160a01b0316836001600160a01b0316856001600160a01b03167fe1b831b0e6f3aa16b4b1a6bd526b5cdeab4940744ca6e0251f5fe5f8caf1c81a60405160405180910390a46040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250505050565b5f61398982614f50565b613994858585612700565b6001600160a01b038581165f818152602081815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928101929092529181019290925291861660608201526080810185905260a081019190915260c08101839052612ba59060e00161320f565b6001600160a01b0381165f9081526020839052604090205460ff1615611694576040517f4f2a367e0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208201526001600160a01b038089169282019290925290861660608201526080810185905260a0810184905260c0810183905260e081018290525f9061349c906101000161320f565b824211613b20576040517f498ff9a200000000000000000000000000000000000000000000000000000000815242600482015260248101849052604401611203565b814210613b62576040517fb3fcd33e00000000000000000000000000000000000000000000000000000000815242600482015260248101839052604401611203565b613b6c8682614c46565b6001600160a01b0386165f818152600160208181526040808420868552909152808320805460ff1916909217909155518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a3611f37868686612a24565b613bd56135d4565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00613c008185613a12565b613c0a8184613a12565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526001600160f01b03831660448201527f000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b6001600160a01b0316906323b872dd906064016020604051808303815f875af1158015613c9b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613cbf9190615dde565b506114ac8383613630565b613cd381614156565b611153576040517fdf5167ee0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0061101a565b611b29614f93565b613d4c614f93565b6001600160a01b038116613d8c576040517f6cbbd1d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116947f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b3582612bae565b613dbe614f93565b6001600160a01b038116613dfe576040517f042d717b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116947f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a82612bae565b613e30614f93565b6001600160a01b038116613e70576040517f354368a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116947fc66b3536568140ce119bcc21a4fa7e3449a56fb5f260d32ff8e719230264132c82612bae565b6001600160a01b0383165f908152600660205260408120805460ff16613ec3575f915050611245565b805460018201546101009091046001600160f01b031690613ef69082906dffffffffffffffffffffffffffff1687612b73565b9250826001600160f01b03165f03613f12575f92505050611245565b81546001600160f01b038285018116610100027fff000000000000000000000000000000000000000000000000000000000000ff9092169190911783556004805480831686019092167fffff0000000000000000000000000000000000000000000000000000000000009092169190911790555f84613f9957613f9487611337565b613f9b565b865b6040516001600160f01b03861681529091506001600160a01b0380831691908916907f4f3dc01c04a512d8b0b3b29dd31108ec4a93696f6506c2e8e609aa77953da7599060200160405180910390a36040516001600160f01b03851681526001600160a01b038816905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3866001600160a01b0316816001600160a01b03160361405457505050611245565b61406087828689614387565b5050509392505050565b6001600160a01b038381165f8181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff16611694576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401611203565b6040517f8eaa6ac00000000000000000000000000000000000000000000000000000000081527f6561726e6572735f6c6973745f69676e6f72656400000000000000000000000060048201525f9081907f000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c6001600160a01b031690638eaa6ac090602401602060405180830381865afa1580156141f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906142199190615d98565b14158061101a57506040517fd7d1c1c00000000000000000000000000000000000000000000000000000000081527f6561726e6572730000000000000000000000000000000000000000000000000060048201526001600160a01b0383811660248301527f000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c169063d7d1c1c090604401602060405180830381865afa1580156142c4573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101a9190615dde565b6004546003546001600160f01b03909116906dffffffffffffffffffffffffffff166143148483614fd1565b600480547fffff000000000000000000000000000000000000000000000000000000000000169184036001600160f01b03169190911790556143568382614ff1565b600380546dffffffffffffffffffffffffffff1916919092036dffffffffffffffffffffffffffff16179055505050565b61438f6135d4565b61439883614624565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce006143c38133613a12565b6143cd8186613a12565b6143d78185613a12565b6040516001600160f01b03841681526001600160a01b0380861691908716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3826001600160f01b03165f0361443957506114ac565b6001600160a01b038086165f90815260066020526040808220928716825290208154815460ff91821691168115158115151461453b57816144835761447e89886146ea565b61448e565b61448e89888861501f565b80614526576001600160a01b0388165f90815260066020526040902080547fff000000000000000000000000000000000000000000000000000000000000ff8116610100918290046001600160f01b039081168b01811690920217909155600580547fffff00000000000000000000000000000000000000000000000000000000000081169083168a01909216919091179055614531565b6145318888886147e8565b50505050506114ac565b83546001600160f01b038089166101009092041610156145b15783546040517f03629ea10000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526101009091046001600160f01b03908116602483015288166044820152606401611203565b8161460d5783546001600160f01b0361010080830482168a9003821681027fff000000000000000000000000000000000000000000000000000000000000ff938416178755855481810483168b019092160291161783556125a0565b6125a084848989615150565b5f6112458383615256565b6001600160a01b038116611153576040517f17858bbe0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b6001600160a01b0381165f9081527f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00602052604090205460ff16611153576040517ffc7824790000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b6001600160a01b0382165f90815260066020526040902080546001600160f01b036101009091048116908316811015614771576040517f03629ea10000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526001600160f01b03808316602483015284166044820152606401611203565b81546001600160f01b03918490038216610100027fff000000000000000000000000000000000000000000000000000000000000ff9091161790915560058054808316939093039091167fffff00000000000000000000000000000000000000000000000000000000000090921691909117905550565b6001600160a01b0383165f9081526006602052604081209061480a8484614cfd565b90505f6148178585614d08565b83546001600160f01b0361010080830482168901909116027fff000000000000000000000000000000000000000000000000000000000000ff909116178455600184015490915061487d906dffffffffffffffffffffffffffff90811690831601615287565b6001840180546dffffffffffffffffffffffffffff19166dffffffffffffffffffffffffffff92909216919091179055611f378583614d13565b6148c9816001600160f01b0316614f14565b6001600160a01b0382165f9081526006602052604090205460ff166148f7576148f282826146ea565b614909565b614909828261490461124c565b61501f565b6040516001600160f01b03821681525f906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161374c565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff16611b29576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f64e8d4a510006dffffffffffffffffffffffffffff84166fffffffffffffffffffffffffffffffff84160264e8d4a50fff015b049392505050565b5f6149ef6114e7565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b5f805f614a558686866152d0565b90925090505f826005811115614a6d57614a6d615dfd565b14614a78578161349c565b61349c8782615317565b5f816005811115614a9557614a95615dfd565b03614a9d5750565b6001816005811115614ab157614ab1615dfd565b03614ae8576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002816005811115614afc57614afc615dfd565b03614b33576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003816005811115614b4757614b47615dfd565b03614b7e576040517fbf4bf5b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004816005811115614b9257614b92615dfd565b03614bc9576040517fff551e8900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005816005811115614bdd57614bdd615dfd565b03614c14576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0382165f90815260016020908152604080832084845290915290205460ff1615611694576040517fd309466d0000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015260248101829052604401611203565b5f805f614cc487878787615340565b90925090505f826005811115614cdc57614cdc615dfd565b14614ce75781614cf1565b614cf18882615317565b98975050505050505050565b5f6112458383615422565b5f61124583836154ad565b600480546001600160f01b038082168501167fffff000000000000000000000000000000000000000000000000000000000000909116179055600354614d6e906dffffffffffffffffffffffffffff90811690831601615287565b600380546dffffffffffffffffffffffffffff19166dffffffffffffffffffffffffffff929092169190911790555050565b5f805f614dad858561552d565b90925090505f826005811115614dc557614dc5615dfd565b14614dd05781614dda565b614dda8682615317565b9695505050505050565b5f805f856001600160a01b03168585604051602401614e04929190615e11565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1626ba7e0000000000000000000000000000000000000000000000000000000017905251614e679190615e31565b5f60405180830381855afa9150503d805f8114614e9f576040519150601f19603f3d011682016040523d82523d5f602084013e614ea4565b606091505b5091509150818015614eb857506020815110155b8015614dda575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090614ef69083016020908101908401615d98565b149695505050505050565b61115381614f0d61124c565b600161288a565b805f03611153576040517f77b8dde300000000000000000000000000000000000000000000000000000000815260048101829052602401611203565b80421115611153576040517ff88f049000000000000000000000000000000000000000000000000000000000815260048101829052426024820152604401611203565b614f9b615571565b611b29576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f816001600160f01b0316836001600160f01b0316106114055781611245565b5f816dffffffffffffffffffffffffffff16836dffffffffffffffffffffffffffff16106114055781611245565b6001600160a01b0383165f90815260066020526040902080546001600160f01b0361010090910481169084168110156150a6576040517f03629ea10000000000000000000000000000000000000000000000000000000081526001600160a01b03861660048201526001600160f01b03808316602483015285166044820152606401611203565b60018201546dffffffffffffffffffffffffffff165f6150c68686614cfd565b90505f6150d38787614d08565b85547fff000000000000000000000000000000000000000000000000000000000000ff166101008987036001600160f01b03160217865590506151168284614ff1565b6001860180546dffffffffffffffffffffffffffff19169185036dffffffffffffffffffffffffffff16919091179055611c1e87826142e8565b60018401546dffffffffffffffffffffffffffff165f6151796151738585614cfd565b83614ff1565b86546001600160f01b036101008083048216889003821681027fff000000000000000000000000000000000000000000000000000000000000ff938416178a556001808b0180546dffffffffffffffffffffffffffff878a0381166dffffffffffffffffffffffffffff19909216919091179091558a5483810485168b01909416909202929093169190911788559087015491925061521d91811690831601615287565b60019590950180546dffffffffffffffffffffffffffff19166dffffffffffffffffffffffffffff909616959095179094555050505050565b5f64e8d4a510006dffffffffffffffffffffffffffff84166fffffffffffffffffffffffffffffffff8416026149de565b5f6dffffffffffffffffffffffffffff821115611b15576040517fca21dbd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80601b60ff84901c017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841661530987838884615340565b935093505050935093915050565b5f816001600160a01b0316836001600160a01b031614615338576005611245565b505f92915050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156153755750600390505f615419565b8460ff16601b1415801561538d57508460ff16601c14155b1561539d5750600490505f615419565b604080515f81526020810180835288905260ff871691810191909152606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156153ed573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811615615410575f81615414565b60015f5b915091505b94509492505050565b5f816fffffffffffffffffffffffffffffffff165f0361546e576040517f23d359a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112456fffffffffffffffffffffffffffffffff83165f196001600160f01b03861664e8d4a5100002820101816154a7576154a7615d45565b04615287565b5f816fffffffffffffffffffffffffffffffff165f036154f9576040517f23d359a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112456fffffffffffffffffffffffffffffffff83166001600160f01b03851664e8d4a5100002816154a7576154a7615d45565b5f8082516041146155435750600290505f61556a565b6020830151604084015160608501515f1a919061556287848484615340565b945094505050505b9250929050565b5f61557a613d14565b5468010000000000000000900460ff16919050565b5f6020828403121561559f575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611245575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61124560208301846155ce565b6001600160a01b0381168114611153575f80fd5b5f8060408385031215615633575f80fd5b823561563e8161560e565b946020939093013593505050565b5f8083601f84011261565c575f80fd5b50813567ffffffffffffffff811115615673575f80fd5b6020830191508360208260051b850101111561556a575f80fd5b5f806020838503121561569e575f80fd5b823567ffffffffffffffff8111156156b4575f80fd5b6156c08582860161564c565b90969095509350505050565b5f602082840312156156dc575f80fd5b81356112458161560e565b5f805f606084860312156156f9575f80fd5b83356157048161560e565b925060208401356157148161560e565b929592945050506040919091013590565b5f60208284031215615735575f80fd5b5035919050565b5f806040838503121561574d575f80fd5b82359150602083013561575f8161560e565b809150509250929050565b5f805f806080858703121561577d575f80fd5b84356157888161560e565b966020860135965060408601359560600135945092505050565b803560ff81168114613798575f80fd5b5f805f805f60a086880312156157c6575f80fd5b85356157d18161560e565b9450602086013593506157e6604087016157a2565b94979396509394606081013594506080013592915050565b7fff000000000000000000000000000000000000000000000000000000000000008816815260e060208201525f61583860e08301896155ce565b828103604084015261584a81896155ce565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b8181101561589f578351835260209384019390920191600101615881565b50909b9a5050505050505050505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126158d3575f80fd5b813567ffffffffffffffff8111156158ed576158ed6158b0565b604051601f19603f601f19601f8501160116810181811067ffffffffffffffff8211171561591d5761591d6158b0565b604052818152838201602001851015615934575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f805f60e0888a031215615966575f80fd5b87356159718161560e565b965060208801356159818161560e565b955060408801359450606088013593506080880135925060a0880135915060c088013567ffffffffffffffff8111156159b8575f80fd5b6159c48a828b016158c4565b91505092959891949750929550565b5f805f805f60a086880312156159e7575f80fd5b85356159f28161560e565b94506020860135615a028161560e565b93506040860135925060608601359150608086013567ffffffffffffffff811115615a2b575f80fd5b615a37888289016158c4565b9150509295509295909350565b5f805f805f805f80610100898b031215615a5c575f80fd5b8835615a678161560e565b97506020890135615a778161560e565b979a9799505050506040860135956060810135956080820135955060a0820135945060c0820135935060e0909101359150565b5f805f60608486031215615abc575f80fd5b8335615ac78161560e565b925060208401359150604084013567ffffffffffffffff811115615ae9575f80fd5b615af5868287016158c4565b9150509250925092565b5f805f805f8060c08789031215615b14575f80fd5b8635615b1f8161560e565b95506020870135615b2f8161560e565b94506040870135615b3f8161560e565b93506060870135615b4f8161560e565b92506080870135615b5f8161560e565b915060a0870135615b6f8161560e565b809150509295509295509295565b5f805f805f805f60e0888a031215615b93575f80fd5b8735615b9e8161560e565b96506020880135615bae8161560e565b95506040880135945060608801359350615bca608089016157a2565b9699959850939692959460a0840135945060c09093013592915050565b5f805f805f8060608789031215615bfc575f80fd5b863567ffffffffffffffff811115615c12575f80fd5b615c1e89828a0161564c565b909750955050602087013567ffffffffffffffff811115615c3d575f80fd5b615c4989828a0161564c565b909550935050604087013567ffffffffffffffff811115615c68575f80fd5b615c7489828a0161564c565b979a9699509497509295939492505050565b5f8060408385031215615c97575f80fd5b8235615ca28161560e565b9150602083013561575f8161560e565b5f805f805f805f805f6101208a8c031215615ccb575f80fd5b8935615cd68161560e565b985060208a0135615ce68161560e565b975060408a0135965060608a0135955060808a0135945060a08a01359350615d1060c08b016157a2565b989b979a50959894979396929550929360e081013593506101000135919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b5f60208284031215615d69575f80fd5b81516112458161560e565b5f5f198203615d9157634e487b7160e01b5f52601160045260245ffd5b5060010190565b5f60208284031215615da8575f80fd5b5051919050565b5f60208284031215615dbf575f80fd5b81516fffffffffffffffffffffffffffffffff81168114611245575f80fd5b5f60208284031215615dee575f80fd5b81518015158114611245575f80fd5b634e487b7160e01b5f52602160045260245ffd5b828152604060208201525f615e2960408301846155ce565b949350505050565b5f82518060208501845e5f92019182525091905056fea2646970667358221220e7d9398909f8ab8c8a3262677c574a016e0df7393e1c6911d269e9ef261ab28d64736f6c634300081a0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":4150},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["@ensdomains/=lib/evm-m-extensions/lib/uniswap-v4-periphery/lib/v4-core/node_modules/@ensdomains/","@openzeppelin/contracts-upgradeable/=lib/common/lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/common/lib/openzeppelin-contracts/contracts/","@uniswap/v4-core/=lib/evm-m-extensions/lib/uniswap-v4-periphery/lib/v4-core/","common/=lib/common/src/","ds-test/=lib/common/lib/safe-utils/lib/solidity-stringutils/lib/ds-test/src/","erc4626-tests/=lib/common/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","evm-m-extensions/=lib/evm-m-extensions/","forge-gas-snapshot/=lib/evm-m-extensions/lib/uniswap-v4-periphery/lib/permit2/lib/forge-gas-snapshot/src/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/common/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/","hardhat/=lib/evm-m-extensions/lib/uniswap-v4-periphery/lib/v4-core/node_modules/hardhat/","openzeppelin-contracts-upgradeable/=lib/common/lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/common/lib/openzeppelin-contracts/","openzeppelin-foundry-upgrades/=lib/evm-m-extensions/lib/openzeppelin-foundry-upgrades/src/","permit2/=lib/evm-m-extensions/lib/uniswap-v4-periphery/lib/permit2/","safe-smart-account/=lib/common/lib/safe-utils/lib/safe-smart-account/","safe-utils/=lib/common/lib/safe-utils/src/","solidity-http/=lib/common/lib/safe-utils/lib/solidity-http/src/","solidity-stringutils/=lib/common/lib/safe-utils/lib/solidity-stringutils/","solmate/=lib/evm-m-extensions/lib/uniswap-v4-periphery/lib/v4-core/lib/solmate/","uniswap-v4-periphery/=lib/evm-m-extensions/lib/uniswap-v4-periphery/","v4-core/=lib/evm-m-extensions/lib/uniswap-v4-periphery/lib/v4-core/src/","wrapped-m-token/=lib/evm-m-extensions/lib/wrapped-m-token/"],"viaIR":false},"optimization_runs":4150,"sourcify_repo_url":null,"decoded_constructor_args":[["0x866A2BF4E572CbcF37D5071A7a58503Bfb36be1b",{"internalType":"address","name":"mToken_","type":"address"}],["0x119FbeeDD4F4f4298Fb59B720d5654442b81ae2c",{"internalType":"address","name":"registrar_","type":"address"}],["0xB6807116b3B1B321a390594e31ECD6e0076f6278",{"internalType":"address","name":"swapFacility_","type":"address"}],["0xf7298F047F92d0Eb21231478Ef6ba9FE1eCD4c73",{"internalType":"address","name":"migrationAdmin_","type":"address"}]],"compiler_version":"v0.8.26+commit.8a97fa7a","is_verified_via_verifier_alliance":false,"verified_at":"2026-07-30T20:23:43.659149Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6101c0604052348015610010575f80fd5b5060405161642838038061642883398101604081905261002f91610401565b6040518060400160405280601181526020017004d20285772617070656429206279204d3607c1b81525060405180604001604052806002815260200161774d60f01b81525060068280806100888161017f60201b60201c565b60e052466080523060c05261009b6101af565b60a052506100ac915083905061017f565b6101205260ff1661010052506100c29050610249565b6001600160a01b0384166101608190526100ef5760405163b01d5e2b60e01b815260040160405180910390fd5b6001600160a01b03831661018081905261011c576040516379a6314960e01b815260040160405180910390fd5b6001600160a01b0382166101a081905261014957604051636880ffc960e11b815260040160405180910390fd5b6001600160a01b0381166101408190526101765760405163ea0b51bb60e01b815260040160405180910390fd5b505050506104da565b5f816040516020016101919190610452565b6040516020818303038152906040526101a990610468565b92915050565b60e0515f907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f906101df906102e6565b80516020918201206040805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f6102526103be565b805490915068010000000000000000900460ff16156102845760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146102e35780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b60605f5b60208110801561030b57508281602081106103075761030761048e565b1a15155b1561032057610319816104a2565b90506102ea565b5f816001600160401b03811115610339576103396104c6565b6040519080825280601f01601f191660200182016040528015610363576020820181803683370190505b5090505f5b828110156103b6578481602081106103825761038261048e565b1a60f81b8282815181106103985761039861048e565b60200101906001600160f81b03191690815f1a905350600101610368565b509392505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006101a9565b80516001600160a01b03811681146103fc575f80fd5b919050565b5f805f8060808587031215610414575f80fd5b61041d856103e6565b935061042b602086016103e6565b9250610439604086016103e6565b9150610447606086016103e6565b905092959194509250565b5f82518060208501845e5f920191825250919050565b80516020808301519190811015610488575f198160200360031b1b821691505b50919050565b634e487b7160e01b5f52603260045260245ffd5b5f600182016104bf57634e487b7160e01b5f52601160045260245ffd5b5060010190565b634e487b7160e01b5f52604160045260245ffd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a051615e7d6105ab5f395f8181610d48015281816115cc0152611f8201525f818161078601528181612b3c015281816141a8015261427f01525f8181610d9501528181611d0c0152818161211c015281816129b801528181612a42015281816130130152613c4d01525f8181610a4b01526123db01525f611b3201525f61084c01525f81816110270152818161197f0152612e4701525f6114f301525f61154e01525f61151d0152615e7d5ff3fe608060405234801561000f575f80fd5b50600436106105c2575f3560e01c8063845828ad116102fc578063aae5e0c01161019d578063d505accf116100f3578063e3ee160e1161009e578063e94a010211610079578063e94a010214610f35578063e9ef148a14610f62578063ef55bec614610f75575f80fd5b8063e3ee160e14610eb1578063e583983614610ec4578063e63ab1e914610f0e575f80fd5b8063d9169487116100ce578063d916948714610e4d578063dd62ed3e14610e74578063ddeae03314610e9e575f80fd5b8063d505accf14610e14578063d547741f14610e27578063d7a49f0b14610e3a575f80fd5b8063c3b6f93911610153578063cc2a9a5b1161012e578063cc2a9a5b14610ddb578063ce5494bb14610dee578063cf09299514610e01575f80fd5b8063c3b6f93914610d90578063c9144ddb14610db7578063c967891a14610dd3575f80fd5b8063ae06b7e411610183578063ae06b7e414610d43578063b7b7289914610d6a578063bf376c7a14610d7d575f80fd5b8063aae5e0c014610d1d578063ace150a514610d30575f80fd5b80639a62984911610252578063a15e66bf11610208578063a8afc01f116101e3578063a8afc01f14610cef578063a9059cbb14610cf7578063aad1202914610d0a575f80fd5b8063a15e66bf14610c91578063a217fddf14610cb8578063a6378a2a14610cbf575f80fd5b80639fd5a6cf116102385780639fd5a6cf14610c44578063a08cb48b14610c57578063a0cc6a6814610c6a575f80fd5b80639a62984914610be25780639f3cbddf14610c09575f80fd5b80638d1fdf2f116102b257806391d148541161028d57806391d1485414610b7057806395d89b4114610bc7578063988cffc714610bcf575f80fd5b80638d1fdf2f14610b4d5780638d78bf7e14610b605780638fd3ab8014610b68575f80fd5b806384b0196e116102e257806384b0196e14610b0c57806388b7ab6314610b275780638a75f23814610b3a575f80fd5b8063845828ad14610ace57806384af270f14610ae1575f80fd5b80633644e515116104665780635a734520116103bc57806370a08231116103725780637ecebe001161034d5780637ecebe0014610a805780637f2eecc314610a9f5780638456cb5914610ac6575f80fd5b806370a0823114610a1057806374df255814610a4657806374edaa2014610a6d575f80fd5b80635c975abb116103a25780635c975abb146109ac5780635cf99384146109d657806363f15649146109e9575f80fd5b80635a7345201461095e5780635c60da1b14610985575f80fd5b806345c8b1a61161041c578063532992c5116103f7578063532992c51461093057806356d59ed2146109435780635a049a701461094b575f80fd5b806345c8b1a6146109025780634ebe94e314610915578063505136d51461091d575f80fd5b806337d45aa81161044c57806337d45aa8146108ae57806339f47693146108e75780633f4ba83a146108fa575f80fd5b80633644e5151461089357806336568abe1461089b575f80fd5b8063248a9ca31161051b5780632c786163116104d157806330adf81f116104ac57806330adf81f14610820578063313ce5671461084757806333bebb7714610880575f80fd5b80632c786163146107d35780632cfd442d146107e65780632f2ff15d1461080d575f80fd5b8063281b229d11610501578063281b229d146107565780632b20e397146107815780632b2134ea146107c0575f80fd5b8063248a9ca31461070d57806326987b601461074e575f80fd5b8063112baad71161057b57806318160ddd1161055657806318160ddd146106d75780631ae2379c146106f257806323b872dd146106fa575f80fd5b8063112baad714610688578063170e2070146106af578063174f6ce9146106c4575f80fd5b806306fdde03116105ab57806306fdde031461062b578063095ea7b3146106405780630a85ce8c14610653575f80fd5b806301ffc9a7146105c657806304dfd03d146105ee575b5f80fd5b6105d96105d436600461558f565b610f88565b60405190151581526020015b60405180910390f35b60075461060a906fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020016105e5565b610633611020565b6040516105e591906155fc565b6105d961064e366004615622565b611050565b61067a7f6561726e6572735f6c6973745f69676e6f72656400000000000000000000000081565b6040519081526020016105e5565b61067a7f776d5f6d69677261746f725f763200000000000000000000000000000000000081565b6106c26106bd36600461568d565b611065565b005b6106c26106d23660046156cc565b6110f9565b6005546004546001600160f01b03918216908216011661067a565b61067a611156565b6105d96107083660046156e7565b611192565b61067a61071b366004615725565b5f9081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b61060a61124c565b600554610769906001600160f01b031681565b6040516001600160f01b0390911681526020016105e5565b6107a87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016105e5565b6107a86107ce3660046156cc565b611337565b6107696107e13660046156cc565b61140c565b61067a7fc66b3536568140ce119bcc21a4fa7e3449a56fb5f260d32ff8e719230264132c81565b6106c261081b36600461573c565b611469565b61067a7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61086e7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff90911681526020016105e5565b6106c261088e3660046156e7565b6114b2565b61067a6114e7565b6106c26108a936600461573c565b611570565b6003546108c8906dffffffffffffffffffffffffffff1681565b6040516dffffffffffffffffffffffffffff90911681526020016105e5565b6106c26108f5366004615622565b6115c1565b6106c2611698565b6106c26109103660046156cc565b6116ca565b61076961171e565b6106c261092b3660046156cc565b611759565b6106c261093e36600461576a565b61178c565b6107696117ab565b6106c26109593660046157b2565b6117c7565b61067a7f6561726e6572730000000000000000000000000000000000000000000000000081565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546107a8565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff166105d9565b61067a6109e43660046156cc565b6117e7565b61067a7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b3581565b61067a610a1e3660046156cc565b6001600160a01b03165f9081526006602052604090205461010090046001600160f01b031690565b6107a87f000000000000000000000000000000000000000000000000000000000000000081565b6106c2610a7b3660046156cc565b61182e565b61067a610a8e3660046156cc565b5f6020819052908152604090205481565b61067a7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6106c261188a565b6106c2610adc3660046156cc565b6118bc565b6105d9610aef3660046156cc565b6001600160a01b03165f9081526006602052604090205460ff1690565b610b14611971565b6040516105e597969594939291906157fe565b6106c2610b35366004615950565b611a19565b600454610769906001600160f01b031681565b6106c2610b5b3660046156cc565b611a48565b610769611a9c565b6106c2611b19565b6105d9610b7e36600461573c565b5f9182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610633611b2b565b6106c2610bdd36600461568d565b611b56565b61067a7f29d497e50c7b1bb72d16f5c1dc421a733085f4402f4a65adbb02a4cdc824b0ad81565b6108c8610c173660046156cc565b6001600160a01b03165f908152600660205260409020600101546dffffffffffffffffffffffffffff1690565b6106c2610c523660046159d3565b611bee565b6106c2610c65366004615a44565b611bfe565b61067a7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b61067a7f776d5f636c61696d5f6f766572726964655f726563697069656e74000000000081565b61067a5f81565b60075461060a9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6106c2611c28565b6105d9610d05366004615622565b611d74565b6106c2610d1836600461568d565b611d80565b6106c2610d2b36600461568d565b611e0d565b6106c2610d3e366004615a44565b611f3f565b6107a87f000000000000000000000000000000000000000000000000000000000000000081565b6106c2610d78366004615aaa565b611f5f565b6106c2610d8b366004615622565b611f77565b6107a87f000000000000000000000000000000000000000000000000000000000000000081565b6007546fffffffffffffffffffffffffffffffff1615156105d9565b6106c261204b565b6106c2610de9366004615aff565b612172565b6106c2610dfc3660046156cc565b6123d0565b6106c2610e0f366004615950565b61243b565b6106c2610e22366004615b7d565b61245b565b6106c2610e3536600461573c565b61246b565b6106c2610e48366004615be7565b6124ae565b61067a7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b61067a610e82366004615c86565b600260209081525f928352604080842090915290825290205481565b610769610eac3660046156cc565b6125ab565b6106c2610ebf366004615cb2565b6125cf565b6105d9610ed23660046156cc565b6001600160a01b03165f9081527f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00602052604090205460ff1690565b61067a7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6105d9610f43366004615622565b600160209081525f928352604080842090915290825290205460ff1681565b6009546107a8906001600160a01b031681565b6106c2610f83366004615cb2565b6125ef565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061101a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b606061104b7f000000000000000000000000000000000000000000000000000000000000000061260f565b905090565b5f61105c338484612700565b50600192915050565b7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b3561108f81612740565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce005f5b838110156110f2576110ea828686848181106110d0576110d0615d31565b90506020020160208101906110e591906156cc565b61274a565b6001016110b2565b5050505050565b611102816127c3565b61110b8161283f565b6111538161111761124c565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff168061114e575061114e610ed285611337565b61288a565b50565b5f8061116061171e565b6005546001600160f01b03908116919091011690505f61117f3061297e565b6001600160f01b03169190910392915050565b6001600160a01b0383165f9081526002602090815260408083203384529091528120545f198114611234578281101561120c576040517f192b9e4e00000000000000000000000000000000000000000000000000000000815233600482015260248101829052604481018490526064015b60405180910390fd5b6001600160a01b0385165f908152600260209081526040808320338452909152902083820390555b61123f858585612a24565b60019150505b9392505050565b6007545f90819070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16156112ac5760075470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166112b3565b64e8d4a510005b6007549091506fffffffffffffffffffffffffffffffff161561132f5760075461132a906fffffffffffffffffffffffffffffffff166112f1612a3f565b6fffffffffffffffffffffffffffffffff16836fffffffffffffffffffffffffffffffff16028161132457611324615d45565b04612ac0565b611331565b805b91505090565b6001600160a01b0381165f908152600660205260408120600101546e010000000000000000000000000000900460ff161561138a57506001600160a01b039081165f908152600860205260409020541690565b5f6113ee7f776d5f636c61696d5f6f766572726964655f726563697069656e740000000000846040516020016113d39291909182526001600160a01b0316602082015260400190565b60405160208183030381529060405280519060200120612b0b565b90506001600160a01b038116156114055780611245565b5090919050565b6001600160a01b0381165f908152600660205260408120805460ff16611432575f611245565b805460018201546112459161010090046001600160f01b0316906dffffffffffffffffffffffffffff1661146461124c565b612b73565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546114a281612740565b6114ac8383612bae565b50505050565b7fc66b3536568140ce119bcc21a4fa7e3449a56fb5f260d32ff8e719230264132c6114dc81612740565b6114ac848484612c7a565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561153f57507f000000000000000000000000000000000000000000000000000000000000000046145b61154b5761104b612e20565b507f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b03811633146115b2576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115bc8282612ed5565b505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611623576040517f2bfe1b5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611694336001600160a01b031663d737d0c76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611662573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116869190615d59565b61168f83612f79565b612fbb565b5050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6116c281612740565b611153613085565b7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b356116f481612740565b6116947f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce008361274a565b6003545f9061104b90611748906dffffffffffffffffffffffffffff1661174361124c565b6130f7565b6004546001600160f01b0316613102565b7f29d497e50c7b1bb72d16f5c1dc421a733085f4402f4a65adbb02a4cdc824b0ad61178381612740565b61169482613122565b6117a18461179a86866131c3565b848461322a565b6114ac848461323e565b6004545f906001600160f01b03166117c161171e565b03905090565b6117dd856117d587876131c3565b8585856132a2565b6110f2858561323e565b5f6117f18261140c565b6001600160f01b0316611827836001600160a01b03165f908152600660205260409020546001600160f01b036101009091041690565b0192915050565b6007546fffffffffffffffffffffffffffffffff16611879576040517fb019ea3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111538161188561124c565b6132b2565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6118b481612740565b6111536133d2565b335f81815260086020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038716908117909155600690925280832060010180547fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff168315156e01000000000000000000000000000002179055519092917f7df311a62f64e432c64a6003630264209cb8dd81c3d59d93031f8e8e72f0657c91a350565b5f6060805f805f60606119a37f000000000000000000000000000000000000000000000000000000000000000061260f565b604080515f8082526060820183526001602083019081527f3100000000000000000000000000000000000000000000000000000000000000938301939093527f0f000000000000000000000000000000000000000000000000000000000000009b939a5091985046975030965090945092509050565b611a3187611a2b89898989898961342d565b836134a7565b611a3f8787878787876134f2565b50505050505050565b7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b35611a7281612740565b6116947f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce0083613553565b5f611aa56135d4565b5f611aae611156565b90505f8113611abe575f91505090565b6040516001600160f01b038216815290915081907f49ec4048a361156a5338ff734a59a750f44cb5753bbe0886c6f39289bec2a0149060200160405180910390a1600954611b15906001600160a01b031683613630565b5090565b611b29611b24613758565b61379d565b565b606061104b7f000000000000000000000000000000000000000000000000000000000000000061260f565b6007546fffffffffffffffffffffffffffffffff16611ba1576040517fb019ea3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611baa61124c565b90505f5b828110156114ac57611be6848483818110611bcb57611bcb615d31565b9050602002016020810190611be091906156cc565b836132b2565b600101611bae565b6110f285611a2b8787878761397f565b611c108861179a8a8a8a8a8a8a61342d565b611c1e8888888888886134f2565b5050505050505050565b611c313061283f565b6007546fffffffffffffffffffffffffffffffff16611c7c576040517fb019ea3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fee580fdb4da10ea17aa673e6f5c8c2370b4166d6a94bc88900e5a96d0589e3ce611ca561124c565b600780546fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009390911692830217905560405190815260200160405180910390a160075f6101000a8154906fffffffffffffffffffffffffffffffff02191690557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639f8495f96040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611d62575f80fd5b505af11580156114ac573d5f803e3d5ffd5b5f61105c338484612a24565b7f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b35611daa81612740565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce005f5b838110156110f257611e0582868684818110611deb57611deb615d31565b9050602002016020810190611e0091906156cc565b613553565b600101611dcd565b5f611e1661124c565b90505f611e447fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1690565b90507f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce005f5b84811015611f3757611ea182878784818110611e8757611e87615d31565b9050602002016020810190611e9c91906156cc565b613a12565b611ed0868683818110611eb657611eb6615d31565b9050602002016020810190611ecb91906156cc565b61283f565b611f2f868683818110611ee557611ee5615d31565b9050602002016020810190611efa91906156cc565b85858061114e575061114e610ed28a8a87818110611f1a57611f1a615d31565b90506020020160208101906107ce91906156cc565b600101611e69565b505050505050565b611f518861179a8a8a8a8a8a8a613a6f565b611c1e888888888888613ade565b611f6d83611a2b85856131c3565b6115bc838361323e565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611fd9576040517f2bfe1b5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611694336001600160a01b031663d737d0c76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612018573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061203c9190615d59565b8361204684612f79565b613bcd565b61205430613cca565b6007546fffffffffffffffffffffffffffffffff16156120a0576040517f7a42736800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f5098de6eb11dbd1127cf4dcd5e960e3944d48a7570b9b1939cff715cb35c5a186120c9612a3f565b600780547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff92909216918217905560405190815260200160405180910390a17f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a36e40fc6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611d62575f80fd5b5f61217b613d14565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156121a75750825b90505f8267ffffffffffffffff1660011480156121c35750303b155b9050811580156121d1575080155b15612208576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156122695784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b612271613d3c565b612279613d3c565b612281613d3c565b612289613d3c565b6001600160a01b038b166122c9576040517f7289db0e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122d35f8c612bae565b506001600160a01b038716612313576040517ede954c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61233d7f29d497e50c7b1bb72d16f5c1dc421a733085f4402f4a65adbb02a4cdc824b0ad88612bae565b5061234786613122565b6123508a613d44565b61235989613db6565b61236288613e28565b83156123c35784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612432576040517f51e2625e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111538161379d565b61244d87611a2b898989898989613a6f565b611a3f878787878787613ade565b611a3f876117d58989898961397f565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546124a481612740565b6114ac8383612ed5565b7fc66b3536568140ce119bcc21a4fa7e3449a56fb5f260d32ff8e719230264132c6124d881612740565b8584811415806124e85750808314155b1561251f576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b818110156125a05761259889898381811061253e5761253e615d31565b905060200201602081019061255391906156cc565b88888481811061256557612565615d31565b905060200201602081019061257a91906156cc565b87878581811061258c5761258c615d31565b90506020020135612c7a565b600101612521565b505050505050505050565b5f6125b46135d4565b6125bd826127c3565b61101a826125c961124c565b5f613e9a565b6125e1896117d58b8b8b8b8b8b613a6f565b6125a0898989898989613ade565b612601896117d58b8b8b8b8b8b61342d565b6125a08989898989896134f2565b60605f5b602081108015612634575082816020811061263057612630615d31565b1a15155b156126495761264281615d74565b9050612613565b5f8167ffffffffffffffff811115612663576126636158b0565b6040519080825280601f01601f19166020018201604052801561268d576020820181803683370190505b5090505f5b828110156126f8578481602081106126ac576126ac615d31565b1a60f81b8282815181106126c2576126c2615d31565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600101612692565b509392505050565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce0061272b8185613a12565b6127358184613a12565b6114ac84848461406a565b61115381336140ca565b6001600160a01b0381165f9081526020839052604090205460ff1661276d575050565b6001600160a01b0381165f8181526020848152604091829020805460ff1916905590514281527f07d647ad688e085159820c1d8d030e5765cdc5274d4ee4065c6066b388a2ef5991015b60405180910390a25050565b6001600160a01b0381165f9081527f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00602052604090205460ff1615611153576040517f4f2a367e0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b61284881614156565b15611153576040517f577be7470000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b6001600160a01b0383165f908152600660205260409020805460ff166128b05750505050565b6128bb848484613e9a565b50805460018201805460ff19831684556dffffffffffffffffffffffffffff1981169091556101009091046001600160f01b0316906dffffffffffffffffffffffffffff1661290a82826142e8565b600580546001600160f01b038082168501167fffff0000000000000000000000000000000000000000000000000000000000009091161790556040516001600160a01b038716907f9467bac89b535c15fcd73b0e7b12e123a045fd17124952dfa868dfdf5e42d48d905f90a2505050505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301525f917f0000000000000000000000000000000000000000000000000000000000000000909116906370a08231906024015b602060405180830381865afa158015612a00573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101a9190615d98565b6115bc8383612a3284612f79565b612a3a61124c565b614387565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326987b606040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a9c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104b9190615daf565b5f6fffffffffffffffffffffffffffffffff821115611b15576040517fec5d4e2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f8eaa6ac0000000000000000000000000000000000000000000000000000000008152600481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638eaa6ac0906024016129e5565b5f80612b7f8484614619565b9050846001600160f01b0316816001600160f01b03161115612ba357848103612ba5565b5f5b95945050505050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff16612c71575f848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055612c273390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505061101a565b5f91505061101a565b612c8382614624565b612c8c8361466f565b612c95826127c3565b5f612c9f82612f79565b6040516001600160f01b03821681529091506001600160a01b0380851691908616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36040516001600160f01b038216815233906001600160a01b0385811691908716907f47cea260e2dfb95ed2ab59ad44fe2ac9cddb432afb828d2a1475936b5a2b829a9060200160405180910390a4806001600160f01b03165f03612d525750505050565b612d5c84826146ea565b6001600160a01b0383165f9081526006602052604090205460ff16612e0e576001600160a01b0383165f90815260066020526040902080547fff000000000000000000000000000000000000000000000000000000000000ff8116610100918290046001600160f01b039081168501811690920217909155600580547fffff000000000000000000000000000000000000000000000000000000000000811690831684019092169190911790556114ac565b6114ac8382612e1b61124c565b6147e8565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f612e6b7f000000000000000000000000000000000000000000000000000000000000000061260f565b80516020918201206040805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff1615612c71575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505061101a565b5f6001600160f01b03821115611b15576040517f2a49c10d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fc36135d4565b612fcc826127c3565b612fd633826148b7565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201526001600160f01b03821660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303815f875af1158015613061573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115bc9190615dde565b61308d61494f565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a150565b5f61124583836149aa565b5f816001600160f01b0316836001600160f01b0316116114055781611245565b6001600160a01b038116613162576040517fc956307100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600980547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f1d7885f1e23525b16c7af644a56936bace8ab48fca508909d54b9bc86186ca37905f90a250565b604080517f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960208201526001600160a01b03841691810191909152606081018290525f90611245906080015b604051602081830303815290604052805190602001206149e6565b6114ac61323985858585614a47565b614a82565b6132488282614c46565b6001600160a01b0382165f818152600160208181526040808420868552909152808320805460ff1916909217909155518392917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a35050565b6110f26132398686868686614cb5565b6132ba6135d4565b6132c3826127c3565b6132cc82613cca565b6001600160a01b0382165f908152600660205260409020805460ff16156132f257505050565b805461010090046001600160f01b03165f61330d8285614cfd565b90505f61331a8386614d08565b8454600160ff1990911681178655850180546dffffffffffffffffffffffffffff19166dffffffffffffffffffffffffffff8316179055905061335d8383614d13565b600580546001600160f01b03808216869003167fffff0000000000000000000000000000000000000000000000000000000000009091161790556040516001600160a01b038716907f8fbc5add0c3fc76c7a869df537ee9250843681f6bbc2ea9735d40c6dc259414c905f90a2505050505050565b6133da6135d4565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336130d9565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208201526001600160a01b038089169282019290925290861660608201526080810185905260a0810184905260c0810183905260e081018290525f9061349c906101000161320f565b979650505050505050565b5f6134b3848484614da0565b90505f8160058111156134c8576134c8615dfd565b036134d35750505050565b6134de848484614de4565b156134e95750505050565b6114ac81614a82565b336001600160a01b03861614613545576040517f1c5939f30000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0386166024820152604401611203565b611f37868686868686613ade565b6001600160a01b0381165f9081526020839052604090205460ff1615613577575050565b61358081614f01565b6001600160a01b0381165f8181526020849052604090819020805460ff19166001179055517f68e0d8c112165d0949ce87205b719ed7d98c7401866c34a159f7c67c6f5620e7906127b79042815260200190565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1615611b29576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613642816001600160f01b0316614f14565b61364b82614624565b6001600160a01b0382165f9081526006602052604090205460ff166136fd576001600160a01b0382165f90815260066020526040902080547fff000000000000000000000000000000000000000000000000000000000000ff8116610100918290046001600160f01b039081168501811690920217909155600580547fffff0000000000000000000000000000000000000000000000000000000000008116908316840190921691909117905561370a565b61370a8282612e1b61124c565b6040516001600160f01b03821681526001600160a01b038316905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b604080517f776d5f6d69677261746f725f7632000000000000000000000000000000000000602082015230918101919091525f90613798906060016113d3565b919050565b6001600160a01b0381166137dd576040517f0d626a3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b5f03613820576040517f8d1e7cf400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6138497f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b90505f826001600160a01b03166040515f60405180830381855af49150503d805f8114613891576040519150601f19603f3d011682016040523d82523d5f602084013e613896565b606091505b50509050806138d1576040517fa27bfda200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6138fa7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050806001600160a01b0316836001600160a01b0316856001600160a01b03167fe1b831b0e6f3aa16b4b1a6bd526b5cdeab4940744ca6e0251f5fe5f8caf1c81a60405160405180910390a46040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250505050565b5f61398982614f50565b613994858585612700565b6001600160a01b038581165f818152602081815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928101929092529181019290925291861660608201526080810185905260a081019190915260c08101839052612ba59060e00161320f565b6001600160a01b0381165f9081526020839052604090205460ff1615611694576040517f4f2a367e0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208201526001600160a01b038089169282019290925290861660608201526080810185905260a0810184905260c0810183905260e081018290525f9061349c906101000161320f565b824211613b20576040517f498ff9a200000000000000000000000000000000000000000000000000000000815242600482015260248101849052604401611203565b814210613b62576040517fb3fcd33e00000000000000000000000000000000000000000000000000000000815242600482015260248101839052604401611203565b613b6c8682614c46565b6001600160a01b0386165f818152600160208181526040808420868552909152808320805460ff1916909217909155518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a3611f37868686612a24565b613bd56135d4565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00613c008185613a12565b613c0a8184613a12565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526001600160f01b03831660448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303815f875af1158015613c9b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613cbf9190615dde565b506114ac8383613630565b613cd381614156565b611153576040517fdf5167ee0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0061101a565b611b29614f93565b613d4c614f93565b6001600160a01b038116613d8c576040517f6cbbd1d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116947f109b88c1c8d528799ca6f455418979dd2a552493f14553ce44443b23f7df8b3582612bae565b613dbe614f93565b6001600160a01b038116613dfe576040517f042d717b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116947f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a82612bae565b613e30614f93565b6001600160a01b038116613e70576040517f354368a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116947fc66b3536568140ce119bcc21a4fa7e3449a56fb5f260d32ff8e719230264132c82612bae565b6001600160a01b0383165f908152600660205260408120805460ff16613ec3575f915050611245565b805460018201546101009091046001600160f01b031690613ef69082906dffffffffffffffffffffffffffff1687612b73565b9250826001600160f01b03165f03613f12575f92505050611245565b81546001600160f01b038285018116610100027fff000000000000000000000000000000000000000000000000000000000000ff9092169190911783556004805480831686019092167fffff0000000000000000000000000000000000000000000000000000000000009092169190911790555f84613f9957613f9487611337565b613f9b565b865b6040516001600160f01b03861681529091506001600160a01b0380831691908916907f4f3dc01c04a512d8b0b3b29dd31108ec4a93696f6506c2e8e609aa77953da7599060200160405180910390a36040516001600160f01b03851681526001600160a01b038816905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3866001600160a01b0316816001600160a01b03160361405457505050611245565b61406087828689614387565b5050509392505050565b6001600160a01b038381165f8181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff16611694576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401611203565b6040517f8eaa6ac00000000000000000000000000000000000000000000000000000000081527f6561726e6572735f6c6973745f69676e6f72656400000000000000000000000060048201525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638eaa6ac090602401602060405180830381865afa1580156141f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906142199190615d98565b14158061101a57506040517fd7d1c1c00000000000000000000000000000000000000000000000000000000081527f6561726e6572730000000000000000000000000000000000000000000000000060048201526001600160a01b0383811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063d7d1c1c090604401602060405180830381865afa1580156142c4573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101a9190615dde565b6004546003546001600160f01b03909116906dffffffffffffffffffffffffffff166143148483614fd1565b600480547fffff000000000000000000000000000000000000000000000000000000000000169184036001600160f01b03169190911790556143568382614ff1565b600380546dffffffffffffffffffffffffffff1916919092036dffffffffffffffffffffffffffff16179055505050565b61438f6135d4565b61439883614624565b7f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce006143c38133613a12565b6143cd8186613a12565b6143d78185613a12565b6040516001600160f01b03841681526001600160a01b0380861691908716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3826001600160f01b03165f0361443957506114ac565b6001600160a01b038086165f90815260066020526040808220928716825290208154815460ff91821691168115158115151461453b57816144835761447e89886146ea565b61448e565b61448e89888861501f565b80614526576001600160a01b0388165f90815260066020526040902080547fff000000000000000000000000000000000000000000000000000000000000ff8116610100918290046001600160f01b039081168b01811690920217909155600580547fffff00000000000000000000000000000000000000000000000000000000000081169083168a01909216919091179055614531565b6145318888886147e8565b50505050506114ac565b83546001600160f01b038089166101009092041610156145b15783546040517f03629ea10000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526101009091046001600160f01b03908116602483015288166044820152606401611203565b8161460d5783546001600160f01b0361010080830482168a9003821681027fff000000000000000000000000000000000000000000000000000000000000ff938416178755855481810483168b019092160291161783556125a0565b6125a084848989615150565b5f6112458383615256565b6001600160a01b038116611153576040517f17858bbe0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b6001600160a01b0381165f9081527f2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00602052604090205460ff16611153576040517ffc7824790000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401611203565b6001600160a01b0382165f90815260066020526040902080546001600160f01b036101009091048116908316811015614771576040517f03629ea10000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526001600160f01b03808316602483015284166044820152606401611203565b81546001600160f01b03918490038216610100027fff000000000000000000000000000000000000000000000000000000000000ff9091161790915560058054808316939093039091167fffff00000000000000000000000000000000000000000000000000000000000090921691909117905550565b6001600160a01b0383165f9081526006602052604081209061480a8484614cfd565b90505f6148178585614d08565b83546001600160f01b0361010080830482168901909116027fff000000000000000000000000000000000000000000000000000000000000ff909116178455600184015490915061487d906dffffffffffffffffffffffffffff90811690831601615287565b6001840180546dffffffffffffffffffffffffffff19166dffffffffffffffffffffffffffff92909216919091179055611f378583614d13565b6148c9816001600160f01b0316614f14565b6001600160a01b0382165f9081526006602052604090205460ff166148f7576148f282826146ea565b614909565b614909828261490461124c565b61501f565b6040516001600160f01b03821681525f906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161374c565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff16611b29576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f64e8d4a510006dffffffffffffffffffffffffffff84166fffffffffffffffffffffffffffffffff84160264e8d4a50fff015b049392505050565b5f6149ef6114e7565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b5f805f614a558686866152d0565b90925090505f826005811115614a6d57614a6d615dfd565b14614a78578161349c565b61349c8782615317565b5f816005811115614a9557614a95615dfd565b03614a9d5750565b6001816005811115614ab157614ab1615dfd565b03614ae8576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002816005811115614afc57614afc615dfd565b03614b33576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003816005811115614b4757614b47615dfd565b03614b7e576040517fbf4bf5b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004816005811115614b9257614b92615dfd565b03614bc9576040517fff551e8900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005816005811115614bdd57614bdd615dfd565b03614c14576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0382165f90815260016020908152604080832084845290915290205460ff1615611694576040517fd309466d0000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015260248101829052604401611203565b5f805f614cc487878787615340565b90925090505f826005811115614cdc57614cdc615dfd565b14614ce75781614cf1565b614cf18882615317565b98975050505050505050565b5f6112458383615422565b5f61124583836154ad565b600480546001600160f01b038082168501167fffff000000000000000000000000000000000000000000000000000000000000909116179055600354614d6e906dffffffffffffffffffffffffffff90811690831601615287565b600380546dffffffffffffffffffffffffffff19166dffffffffffffffffffffffffffff929092169190911790555050565b5f805f614dad858561552d565b90925090505f826005811115614dc557614dc5615dfd565b14614dd05781614dda565b614dda8682615317565b9695505050505050565b5f805f856001600160a01b03168585604051602401614e04929190615e11565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1626ba7e0000000000000000000000000000000000000000000000000000000017905251614e679190615e31565b5f60405180830381855afa9150503d805f8114614e9f576040519150601f19603f3d011682016040523d82523d5f602084013e614ea4565b606091505b5091509150818015614eb857506020815110155b8015614dda575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090614ef69083016020908101908401615d98565b149695505050505050565b61115381614f0d61124c565b600161288a565b805f03611153576040517f77b8dde300000000000000000000000000000000000000000000000000000000815260048101829052602401611203565b80421115611153576040517ff88f049000000000000000000000000000000000000000000000000000000000815260048101829052426024820152604401611203565b614f9b615571565b611b29576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f816001600160f01b0316836001600160f01b0316106114055781611245565b5f816dffffffffffffffffffffffffffff16836dffffffffffffffffffffffffffff16106114055781611245565b6001600160a01b0383165f90815260066020526040902080546001600160f01b0361010090910481169084168110156150a6576040517f03629ea10000000000000000000000000000000000000000000000000000000081526001600160a01b03861660048201526001600160f01b03808316602483015285166044820152606401611203565b60018201546dffffffffffffffffffffffffffff165f6150c68686614cfd565b90505f6150d38787614d08565b85547fff000000000000000000000000000000000000000000000000000000000000ff166101008987036001600160f01b03160217865590506151168284614ff1565b6001860180546dffffffffffffffffffffffffffff19169185036dffffffffffffffffffffffffffff16919091179055611c1e87826142e8565b60018401546dffffffffffffffffffffffffffff165f6151796151738585614cfd565b83614ff1565b86546001600160f01b036101008083048216889003821681027fff000000000000000000000000000000000000000000000000000000000000ff938416178a556001808b0180546dffffffffffffffffffffffffffff878a0381166dffffffffffffffffffffffffffff19909216919091179091558a5483810485168b01909416909202929093169190911788559087015491925061521d91811690831601615287565b60019590950180546dffffffffffffffffffffffffffff19166dffffffffffffffffffffffffffff909616959095179094555050505050565b5f64e8d4a510006dffffffffffffffffffffffffffff84166fffffffffffffffffffffffffffffffff8416026149de565b5f6dffffffffffffffffffffffffffff821115611b15576040517fca21dbd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80601b60ff84901c017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841661530987838884615340565b935093505050935093915050565b5f816001600160a01b0316836001600160a01b031614615338576005611245565b505f92915050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156153755750600390505f615419565b8460ff16601b1415801561538d57508460ff16601c14155b1561539d5750600490505f615419565b604080515f81526020810180835288905260ff871691810191909152606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156153ed573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811615615410575f81615414565b60015f5b915091505b94509492505050565b5f816fffffffffffffffffffffffffffffffff165f0361546e576040517f23d359a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112456fffffffffffffffffffffffffffffffff83165f196001600160f01b03861664e8d4a5100002820101816154a7576154a7615d45565b04615287565b5f816fffffffffffffffffffffffffffffffff165f036154f9576040517f23d359a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112456fffffffffffffffffffffffffffffffff83166001600160f01b03851664e8d4a5100002816154a7576154a7615d45565b5f8082516041146155435750600290505f61556a565b6020830151604084015160608501515f1a919061556287848484615340565b945094505050505b9250929050565b5f61557a613d14565b5468010000000000000000900460ff16919050565b5f6020828403121561559f575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611245575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61124560208301846155ce565b6001600160a01b0381168114611153575f80fd5b5f8060408385031215615633575f80fd5b823561563e8161560e565b946020939093013593505050565b5f8083601f84011261565c575f80fd5b50813567ffffffffffffffff811115615673575f80fd5b6020830191508360208260051b850101111561556a575f80fd5b5f806020838503121561569e575f80fd5b823567ffffffffffffffff8111156156b4575f80fd5b6156c08582860161564c565b90969095509350505050565b5f602082840312156156dc575f80fd5b81356112458161560e565b5f805f606084860312156156f9575f80fd5b83356157048161560e565b925060208401356157148161560e565b929592945050506040919091013590565b5f60208284031215615735575f80fd5b5035919050565b5f806040838503121561574d575f80fd5b82359150602083013561575f8161560e565b809150509250929050565b5f805f806080858703121561577d575f80fd5b84356157888161560e565b966020860135965060408601359560600135945092505050565b803560ff81168114613798575f80fd5b5f805f805f60a086880312156157c6575f80fd5b85356157d18161560e565b9450602086013593506157e6604087016157a2565b94979396509394606081013594506080013592915050565b7fff000000000000000000000000000000000000000000000000000000000000008816815260e060208201525f61583860e08301896155ce565b828103604084015261584a81896155ce565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b8181101561589f578351835260209384019390920191600101615881565b50909b9a5050505050505050505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126158d3575f80fd5b813567ffffffffffffffff8111156158ed576158ed6158b0565b604051601f19603f601f19601f8501160116810181811067ffffffffffffffff8211171561591d5761591d6158b0565b604052818152838201602001851015615934575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f805f60e0888a031215615966575f80fd5b87356159718161560e565b965060208801356159818161560e565b955060408801359450606088013593506080880135925060a0880135915060c088013567ffffffffffffffff8111156159b8575f80fd5b6159c48a828b016158c4565b91505092959891949750929550565b5f805f805f60a086880312156159e7575f80fd5b85356159f28161560e565b94506020860135615a028161560e565b93506040860135925060608601359150608086013567ffffffffffffffff811115615a2b575f80fd5b615a37888289016158c4565b9150509295509295909350565b5f805f805f805f80610100898b031215615a5c575f80fd5b8835615a678161560e565b97506020890135615a778161560e565b979a9799505050506040860135956060810135956080820135955060a0820135945060c0820135935060e0909101359150565b5f805f60608486031215615abc575f80fd5b8335615ac78161560e565b925060208401359150604084013567ffffffffffffffff811115615ae9575f80fd5b615af5868287016158c4565b9150509250925092565b5f805f805f8060c08789031215615b14575f80fd5b8635615b1f8161560e565b95506020870135615b2f8161560e565b94506040870135615b3f8161560e565b93506060870135615b4f8161560e565b92506080870135615b5f8161560e565b915060a0870135615b6f8161560e565b809150509295509295509295565b5f805f805f805f60e0888a031215615b93575f80fd5b8735615b9e8161560e565b96506020880135615bae8161560e565b95506040880135945060608801359350615bca608089016157a2565b9699959850939692959460a0840135945060c09093013592915050565b5f805f805f8060608789031215615bfc575f80fd5b863567ffffffffffffffff811115615c12575f80fd5b615c1e89828a0161564c565b909750955050602087013567ffffffffffffffff811115615c3d575f80fd5b615c4989828a0161564c565b909550935050604087013567ffffffffffffffff811115615c68575f80fd5b615c7489828a0161564c565b979a9699509497509295939492505050565b5f8060408385031215615c97575f80fd5b8235615ca28161560e565b9150602083013561575f8161560e565b5f805f805f805f805f6101208a8c031215615ccb575f80fd5b8935615cd68161560e565b985060208a0135615ce68161560e565b975060408a0135965060608a0135955060808a0135945060a08a01359350615d1060c08b016157a2565b989b979a50959894979396929550929360e081013593506101000135919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b5f60208284031215615d69575f80fd5b81516112458161560e565b5f5f198203615d9157634e487b7160e01b5f52601160045260245ffd5b5060010190565b5f60208284031215615da8575f80fd5b5051919050565b5f60208284031215615dbf575f80fd5b81516fffffffffffffffffffffffffffffffff81168114611245575f80fd5b5f60208284031215615dee575f80fd5b81518015158114611245575f80fd5b634e487b7160e01b5f52602160045260245ffd5b828152604060208201525f615e2960408301846155ce565b949350505050565b5f82518060208501845e5f92019182525091905056fea2646970667358221220e7d9398909f8ab8c8a3262677c574a016e0df7393e1c6911d269e9ef261ab28d64736f6c634300081a0033000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c000000000000000000000000b6807116b3b1b321a390594e31ecd6e0076f6278000000000000000000000000f7298f047f92d0eb21231478ef6ba9fe1ecd4c73","name":"WrappedMToken","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"lib/common/src/libs/Bytes32String.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\n/**\n * @title  A library to convert between string and bytes32 (assuming 32 characters or less).\n * @author M^0 Labs\n */\nlibrary Bytes32String {\n    function toBytes32(string memory input) internal pure returns (bytes32) {\n        return bytes32(abi.encodePacked(input));\n    }\n\n    function toString(bytes32 input) internal pure returns (string memory) {\n        uint256 length;\n\n        while (length < 32 && uint8(input[length]) != 0) {\n            ++length;\n        }\n\n        bytes memory name = new bytes(length);\n\n        for (uint256 index; index < length; ++index) {\n            name[index] = input[index];\n        }\n\n        return string(name);\n    }\n}\n"},{"file_path":"lib/common/src/interfaces/IERC20Extended.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IERC20 } from \"./IERC20.sol\";\nimport { IERC3009 } from \"./IERC3009.sol\";\n\n/**\n * @title  An ERC20 token extended with EIP-2612 permits for signed approvals (via EIP-712\n *         and with EIP-1271 compatibility), and extended with EIP-3009 transfer with authorization (via EIP-712).\n * @author M^0 Labs\n * @dev    The additional interface as defined by EIP-2612: https://eips.ethereum.org/EIPS/eip-2612\n */\ninterface IERC20Extended is IERC20, IERC3009 {\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when spender's allowance is not sufficient.\n     * @param  spender    Address that may be allowed to operate on tokens without being their owner.\n     * @param  allowance  Amount of tokens a `spender` is allowed to operate with.\n     * @param  needed     Minimum amount required to perform a transfer.\n     */\n    error InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @notice Revert message emitted when the transferred amount is insufficient.\n     * @param  amount Amount transferred.\n     */\n    error InsufficientAmount(uint256 amount);\n\n    /**\n     * @notice Revert message emitted when the recipient of a token is invalid.\n     * @param  recipient Address of the invalid recipient.\n     */\n    error InvalidRecipient(address recipient);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Approves `spender` to spend up to `amount` of the token balance of `owner`, via a signature.\n     * @param  owner    The address of the account who's token balance is being approved to be spent by `spender`.\n     * @param  spender  The address of an account allowed to spend on behalf of `owner`.\n     * @param  value    The amount of the allowance being approved.\n     * @param  deadline The last timestamp where the signature is still valid.\n     * @param  v        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     * @param  r        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     * @param  s        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Approves `spender` to spend up to `amount` of the token balance of `owner`, via a signature.\n     * @param  owner     The address of the account who's token balance is being approved to be spent by `spender`.\n     * @param  spender   The address of an account allowed to spend on behalf of `owner`.\n     * @param  value     The amount of the allowance being approved.\n     * @param  deadline  The last timestamp where the signature is still valid.\n     * @param  signature An arbitrary signature (EIP-712).\n     */\n    function permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the EIP712 typehash used in the encoding of the digest for the permit function.\n    function PERMIT_TYPEHASH() external view returns (bytes32);\n}\n"},{"file_path":"lib/common/src/interfaces/IERC712Extended.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IERC712 } from \"./IERC712.sol\";\n\n/**\n * @title  EIP-712 extended by EIP-5267.\n * @author M^0 Labs\n * @dev    The additional interface as defined by EIP-5267: https://eips.ethereum.org/EIPS/eip-5267\n */\ninterface IERC712Extended is IERC712 {\n    /* ============ Events ============ */\n\n    /// @notice MAY be emitted to signal that the domain could have changed.\n    event EIP712DomainChanged();\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the fields and values that describe the domain separator used by this contract for EIP-712.\n    function eip712Domain()\n        external\n        view\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        );\n}\n"},{"file_path":"lib/evm-m-extensions/lib/common/lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControl} from \"@openzeppelin/contracts/access/IAccessControl.sol\";\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {ERC165Upgradeable} from \"../utils/introspection/ERC165Upgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {\n    struct RoleData {\n        mapping(address account => bool) hasRole;\n        bytes32 adminRole;\n    }\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl\n    struct AccessControlStorage {\n        mapping(bytes32 role => RoleData) _roles;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.AccessControl\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;\n\n    function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {\n        assembly {\n            $.slot := AccessControlStorageLocation\n        }\n    }\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with an {AccessControlUnauthorizedAccount} error including the required role.\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    function __AccessControl_init() internal onlyInitializing {\n    }\n\n    function __AccessControl_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        return $._roles[role].hasRole[account];\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n     * is missing `role`.\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert AccessControlUnauthorizedAccount(account, role);\n        }\n    }\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 {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        return $._roles[role].adminRole;\n    }\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     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\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     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\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 revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n        if (callerConfirmation != _msgSender()) {\n            revert AccessControlBadConfirmation();\n        }\n\n        _revokeRole(role, callerConfirmation);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        $._roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        if (!hasRole(role, account)) {\n            $._roles[role].hasRole[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        if (hasRole(role, account)) {\n            $._roles[role].hasRole[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"},{"file_path":"lib/evm-m-extensions/lib/common/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.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 reinitialization) 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 Pointer to storage slot. Allows integrators to override it with a custom storage location.\n     *\n     * NOTE: Consider following the ERC-7201 formula to derive storage locations.\n     */\n    function _initializableStorageSlot() internal pure virtual returns (bytes32) {\n        return INITIALIZABLE_STORAGE;\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        bytes32 slot = _initializableStorageSlot();\n        assembly {\n            $.slot := slot\n        }\n    }\n}\n"},{"file_path":"lib/common/src/ERC3009.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IERC3009 } from \"./interfaces/IERC3009.sol\";\n\nimport { StatefulERC712 } from \"./StatefulERC712.sol\";\n\n/**\n * @title  ERC3009 implementation allowing the transfer of fungible assets via a signed authorization.\n * @author M^0 Labs\n * @dev    Inherits from ERC712 and StatefulERC712.\n */\nabstract contract ERC3009 is IERC3009, StatefulERC712 {\n    /* ============ Variables ============ */\n\n    // solhint-disable-next-line max-line-length\n    /// @dev        keccak256(\"TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)\")\n    /// @inheritdoc IERC3009\n    bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH =\n        0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;\n\n    // solhint-disable-next-line max-line-length\n    /// @dev        keccak256(\"ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)\")\n    /// @inheritdoc IERC3009\n    bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH =\n        0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8;\n\n    /**\n     * @inheritdoc IERC3009\n     * @dev        keccak256(\"CancelAuthorization(address authorizer,bytes32 nonce)\")\n     */\n    bytes32 public constant CANCEL_AUTHORIZATION_TYPEHASH =\n        0x158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a1597429;\n\n    /// @inheritdoc IERC3009\n    mapping(address authorizer => mapping(bytes32 nonce => bool isNonceUsed)) public authorizationState;\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Construct the ERC3009 contract.\n     * @param  name_ The name of the contract.\n     */\n    constructor(string memory name_) StatefulERC712(name_) {}\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IERC3009\n    function transferWithAuthorization(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_,\n        bytes memory signature_\n    ) external {\n        _revertIfInvalidSignature(\n            from_,\n            _getTransferWithAuthorizationDigest(from_, to_, value_, validAfter_, validBefore_, nonce_),\n            signature_\n        );\n\n        _transferWithAuthorization(from_, to_, value_, validAfter_, validBefore_, nonce_);\n    }\n\n    /// @inheritdoc IERC3009\n    function transferWithAuthorization(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_,\n        bytes32 r_,\n        bytes32 vs_\n    ) external {\n        _revertIfInvalidSignature(\n            from_,\n            _getTransferWithAuthorizationDigest(from_, to_, value_, validAfter_, validBefore_, nonce_),\n            r_,\n            vs_\n        );\n\n        _transferWithAuthorization(from_, to_, value_, validAfter_, validBefore_, nonce_);\n    }\n\n    /// @inheritdoc IERC3009\n    function transferWithAuthorization(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) external {\n        _revertIfInvalidSignature(\n            from_,\n            _getTransferWithAuthorizationDigest(from_, to_, value_, validAfter_, validBefore_, nonce_),\n            v_,\n            r_,\n            s_\n        );\n\n        _transferWithAuthorization(from_, to_, value_, validAfter_, validBefore_, nonce_);\n    }\n\n    /// @inheritdoc IERC3009\n    function receiveWithAuthorization(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_,\n        bytes memory signature_\n    ) external {\n        _revertIfInvalidSignature(\n            from_,\n            _getReceiveWithAuthorizationDigest(from_, to_, value_, validAfter_, validBefore_, nonce_),\n            signature_\n        );\n\n        _receiveWithAuthorization(from_, to_, value_, validAfter_, validBefore_, nonce_);\n    }\n\n    /// @inheritdoc IERC3009\n    function receiveWithAuthorization(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_,\n        bytes32 r_,\n        bytes32 vs_\n    ) external {\n        _revertIfInvalidSignature(\n            from_,\n            _getReceiveWithAuthorizationDigest(from_, to_, value_, validAfter_, validBefore_, nonce_),\n            r_,\n            vs_\n        );\n\n        _receiveWithAuthorization(from_, to_, value_, validAfter_, validBefore_, nonce_);\n    }\n\n    /// @inheritdoc IERC3009\n    function receiveWithAuthorization(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) external {\n        _revertIfInvalidSignature(\n            from_,\n            _getReceiveWithAuthorizationDigest(from_, to_, value_, validAfter_, validBefore_, nonce_),\n            v_,\n            r_,\n            s_\n        );\n\n        _receiveWithAuthorization(from_, to_, value_, validAfter_, validBefore_, nonce_);\n    }\n\n    /// @inheritdoc IERC3009\n    function cancelAuthorization(address authorizer_, bytes32 nonce_, bytes memory signature_) external {\n        _revertIfInvalidSignature(authorizer_, _getCancelAuthorizationDigest(authorizer_, nonce_), signature_);\n        _cancelAuthorization(authorizer_, nonce_);\n    }\n\n    /// @inheritdoc IERC3009\n    function cancelAuthorization(address authorizer_, bytes32 nonce_, bytes32 r_, bytes32 vs_) external {\n        _revertIfInvalidSignature(authorizer_, _getCancelAuthorizationDigest(authorizer_, nonce_), r_, vs_);\n        _cancelAuthorization(authorizer_, nonce_);\n    }\n\n    /// @inheritdoc IERC3009\n    function cancelAuthorization(address authorizer_, bytes32 nonce_, uint8 v_, bytes32 r_, bytes32 s_) external {\n        _revertIfInvalidSignature(authorizer_, _getCancelAuthorizationDigest(authorizer_, nonce_), v_, r_, s_);\n        _cancelAuthorization(authorizer_, nonce_);\n    }\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @dev   Common transfer function used by `transferWithAuthorization` and `_receiveWithAuthorization`.\n     * @param from_        Payer's address (Authorizer).\n     * @param to_          Payee's address.\n     * @param value_       Amount to be transferred.\n     * @param validAfter_  The time after which this is valid (unix time).\n     * @param validBefore_ The time before which this is valid (unix time).\n     * @param nonce_       Unique nonce.\n     */\n    function _transferWithAuthorization(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_\n    ) internal {\n        if (block.timestamp <= validAfter_) revert AuthorizationNotYetValid(block.timestamp, validAfter_);\n        if (block.timestamp >= validBefore_) revert AuthorizationExpired(block.timestamp, validBefore_);\n\n        _revertIfAuthorizationAlreadyUsed(from_, nonce_);\n\n        authorizationState[from_][nonce_] = true;\n\n        emit AuthorizationUsed(from_, nonce_);\n\n        _transfer(from_, to_, value_);\n    }\n\n    /**\n     * @dev   Common receive function used by `receiveWithAuthorization`.\n     * @param from_        Payer's address (Authorizer).\n     * @param to_          Payee's address.\n     * @param value_       Amount to be transferred.\n     * @param validAfter_  The time after which this is valid (unix time).\n     * @param validBefore_ The time before which this is valid (unix time).\n     * @param nonce_       Unique nonce.\n     */\n    function _receiveWithAuthorization(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_\n    ) internal {\n        if (msg.sender != to_) revert CallerMustBePayee(msg.sender, to_);\n\n        _transferWithAuthorization(from_, to_, value_, validAfter_, validBefore_, nonce_);\n    }\n\n    /**\n     * @dev   Common cancel function used by `cancelAuthorization`.\n     * @param authorizer_ Authorizer's address.\n     * @param nonce_      Nonce of the authorization.\n     */\n    function _cancelAuthorization(address authorizer_, bytes32 nonce_) internal {\n        _revertIfAuthorizationAlreadyUsed(authorizer_, nonce_);\n\n        authorizationState[authorizer_][nonce_] = true;\n\n        emit AuthorizationCanceled(authorizer_, nonce_);\n    }\n\n    /**\n     * @dev   Internal ERC20 transfer function that needs to be implemented by the inheriting contract.\n     * @param sender_    The sender's address.\n     * @param recipient_ The recipient's address.\n     * @param amount_    The amount to be transferred.\n     */\n    function _transfer(address sender_, address recipient_, uint256 amount_) internal virtual;\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Returns the internal EIP-712 digest of a transferWithAuthorization call.\n     * @param  from_        Payer's address (Authorizer).\n     * @param  to_          Payee's address.\n     * @param  value_       Amount to be transferred.\n     * @param  validAfter_  The time after which this is valid (unix time).\n     * @param  validBefore_ The time before which this is valid (unix time).\n     * @param  nonce_       Unique nonce.\n     * @return The internal EIP-712 digest.\n     */\n    function _getTransferWithAuthorizationDigest(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_\n    ) internal view returns (bytes32) {\n        return\n            _getDigest(\n                keccak256(\n                    abi.encode(\n                        TRANSFER_WITH_AUTHORIZATION_TYPEHASH,\n                        from_,\n                        to_,\n                        value_,\n                        validAfter_,\n                        validBefore_,\n                        nonce_\n                    )\n                )\n            );\n    }\n\n    /**\n     * @dev    Returns the internal EIP-712 digest of a receiveWithAuthorization call.\n     * @param  from_        Payer's address (Authorizer).\n     * @param  to_          Payee's address.\n     * @param  value_       Amount to be transferred.\n     * @param  validAfter_  The time after which this is valid (unix time).\n     * @param  validBefore_ The time before which this is valid (unix time).\n     * @param  nonce_       Unique nonce.\n     * @return The internal EIP-712 digest.\n     */\n    function _getReceiveWithAuthorizationDigest(\n        address from_,\n        address to_,\n        uint256 value_,\n        uint256 validAfter_,\n        uint256 validBefore_,\n        bytes32 nonce_\n    ) internal view returns (bytes32) {\n        return\n            _getDigest(\n                keccak256(\n                    abi.encode(\n                        RECEIVE_WITH_AUTHORIZATION_TYPEHASH,\n                        from_,\n                        to_,\n                        value_,\n                        validAfter_,\n                        validBefore_,\n                        nonce_\n                    )\n                )\n            );\n    }\n\n    /**\n     * @dev    Returns the internal EIP-712 digest of a cancelAuthorization call.\n     * @param  authorizer_ Authorizer's address.\n     * @param  nonce_      Nonce of the authorization.\n     * @return The internal EIP-712 digest.\n     */\n    function _getCancelAuthorizationDigest(address authorizer_, bytes32 nonce_) internal view returns (bytes32) {\n        return _getDigest(keccak256(abi.encode(CANCEL_AUTHORIZATION_TYPEHASH, authorizer_, nonce_)));\n    }\n\n    /**\n     * @dev   Reverts if the authorization is already used.\n     * @param authorizer_ The authorizer's address.\n     * @param nonce_      The nonce of the authorization.\n     */\n    function _revertIfAuthorizationAlreadyUsed(address authorizer_, bytes32 nonce_) internal view {\n        if (authorizationState[authorizer_][nonce_]) revert AuthorizationAlreadyUsed(authorizer_, nonce_);\n    }\n}\n"},{"file_path":"src/interfaces/IMTokenLike.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.26;\n\n/**\n * @title  Subset of M Token interface required for source contracts.\n * @author M0 Labs\n */\ninterface IMTokenLike {\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Approves `spender` to spend up to `amount` of the token balance of `owner`, via a signature.\n     * @param  owner    The address of the account who's token balance is being approved to be spent by `spender`.\n     * @param  spender  The address of an account allowed to spend on behalf of `owner`.\n     * @param  value    The amount of the allowance being approved.\n     * @param  deadline The last timestamp where the signature is still valid.\n     * @param  v        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     * @param  r        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     * @param  s        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Approves `spender` to spend up to `amount` of the token balance of `owner`, via a signature.\n     * @param  owner     The address of the account who's token balance is being approved to be spent by `spender`.\n     * @param  spender   The address of an account allowed to spend on behalf of `owner`.\n     * @param  value     The amount of the allowance being approved.\n     * @param  deadline  The last timestamp where the signature is still valid.\n     * @param  signature An arbitrary signature (EIP-712).\n     */\n    function permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature) external;\n\n    /**\n     * @notice Allows a calling account to transfer `amount` tokens to `recipient`.\n     * @param  recipient The address of the recipient who's token balance will be incremented.\n     * @param  amount    The amount of tokens being transferred.\n     * @return success   Whether or not the transfer was successful.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool success);\n\n    /**\n     * @notice Allows a calling account to transfer `amount` tokens from `sender`, with allowance, to a `recipient`.\n     * @param  sender    The address of the sender who's token balance will be decremented.\n     * @param  recipient The address of the recipient who's token balance will be incremented.\n     * @param  amount    The amount of tokens being transferred.\n     * @return success   Whether or not the transfer was successful.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool success);\n\n    /// @notice Starts earning for caller if allowed by the Registrar.\n    function startEarning() external;\n\n    /// @notice Stops earning for caller.\n    function stopEarning() external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Checks if account is an earner.\n     * @param  account The account to check.\n     * @return earning True if account is an earner, false otherwise.\n     */\n    function isEarning(address account) external view returns (bool earning);\n\n    /**\n     * @notice Returns the token balance of `account`.\n     * @param  account The address of some account.\n     * @return balance The token balance of `account`.\n     */\n    function balanceOf(address account) external view returns (uint256 balance);\n\n    /// @notice The current index that would be written to storage if `updateIndex` is called.\n    function currentIndex() external view returns (uint128 currentIndex);\n\n    /**\n     * @notice The principal of an earner M token balance.\n     * @param  account The account to get the principal balance of.\n     * @return The principal balance of the account.\n     */\n    function principalBalanceOf(address account) external view returns (uint240);\n}\n"},{"file_path":"lib/evm-m-extensions/lib/common/lib/openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.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 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    function __Pausable_init() internal onlyInitializing {\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\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":"lib/common/src/ERC20Extended.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IERC20 } from \"./interfaces/IERC20.sol\";\nimport { IERC20Extended } from \"./interfaces/IERC20Extended.sol\";\n\nimport { Bytes32String } from \"./libs/Bytes32String.sol\";\n\nimport { ERC3009 } from \"./ERC3009.sol\";\n\n/**\n * @title  An ERC20 token extended with EIP-2612 permits for signed approvals (via EIP-712 and with EIP-1271\n *         and EIP-5267 compatibility), and extended with EIP-3009 transfer with authorization (via EIP-712).\n * @author M^0 Labs\n */\nabstract contract ERC20Extended is IERC20Extended, ERC3009 {\n    /* ============ Variables ============ */\n\n    /**\n     * @inheritdoc IERC20Extended\n     * @dev Keeping this constant, despite `permit` parameter name differences, to ensure max EIP-2612 compatibility.\n     *      keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\")\n     */\n    bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n\n    /// @inheritdoc IERC20\n    uint8 public immutable decimals;\n\n    /// @dev The symbol of the token (stored as a bytes32 instead of a string in order to be immutable).\n    bytes32 internal immutable _symbol;\n\n    /// @inheritdoc IERC20\n    mapping(address account => mapping(address spender => uint256 allowance)) public allowance;\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Constructs the ERC20Extended contract.\n     * @param  name_     The name of the token.\n     * @param  symbol_   The symbol of the token.\n     * @param  decimals_ The number of decimals the token uses.\n     */\n    constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC3009(name_) {\n        _symbol = Bytes32String.toBytes32(symbol_);\n        decimals = decimals_;\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IERC20\n    function approve(address spender_, uint256 amount_) external returns (bool success_) {\n        _approve(msg.sender, spender_, amount_);\n        return true;\n    }\n\n    /// @inheritdoc IERC20Extended\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        _revertIfInvalidSignature(owner_, _permitAndGetDigest(owner_, spender_, value_, deadline_), v_, r_, s_);\n    }\n\n    /// @inheritdoc IERC20Extended\n    function permit(\n        address owner_,\n        address spender_,\n        uint256 value_,\n        uint256 deadline_,\n        bytes memory signature_\n    ) external {\n        _revertIfInvalidSignature(owner_, _permitAndGetDigest(owner_, spender_, value_, deadline_), signature_);\n    }\n\n    /// @inheritdoc IERC20\n    function transfer(address recipient_, uint256 amount_) external returns (bool success_) {\n        _transfer(msg.sender, recipient_, amount_);\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function transferFrom(address sender_, address recipient_, uint256 amount_) external returns (bool success_) {\n        uint256 spenderAllowance_ = allowance[sender_][msg.sender]; // Cache `spenderAllowance_` to stack.\n\n        if (spenderAllowance_ != type(uint256).max) {\n            if (spenderAllowance_ < amount_) revert InsufficientAllowance(msg.sender, spenderAllowance_, amount_);\n\n            unchecked {\n                _setAllowance(sender_, msg.sender, spenderAllowance_ - amount_);\n            }\n        }\n\n        _transfer(sender_, recipient_, amount_);\n\n        return true;\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IERC20\n    function name() external view virtual returns (string memory) {\n        return Bytes32String.toString(_name);\n    }\n\n    /// @inheritdoc IERC20\n    function symbol() external view virtual returns (string memory) {\n        return Bytes32String.toString(_symbol);\n    }\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @dev Approve `spender_` to spend `amount_` of tokens from `account_`.\n     * @param  account_ The address approving the allowance.\n     * @param  spender_ The address approved to spend the tokens.\n     * @param  amount_  The amount of tokens being approved for spending.\n     */\n    function _approve(address account_, address spender_, uint256 amount_) internal virtual {\n        _setAllowance(account_, spender_, amount_);\n        emit Approval(account_, spender_, amount_);\n    }\n\n    /**\n     * @dev Set the `amount_` of tokens `spender_` is allowed to spend from `account_`.\n     * @param  account_ The address for which the allowance is set.\n     * @param  spender_ The address allowed to spend the tokens.\n     * @param  amount_  The amount of tokens being allowed for spending.\n     */\n    function _setAllowance(address account_, address spender_, uint256 amount_) internal virtual {\n        allowance[account_][spender_] = amount_;\n    }\n\n    /**\n     * @dev    Performs the approval based on the permit info, validates the deadline, and returns the digest.\n     * @param  owner_    The address of the account approving the allowance.\n     * @param  spender_  The address of the account being allowed to spend the tokens.\n     * @param  amount_   The amount of tokens being approved for spending.\n     * @param  deadline_ The deadline by which the signature must be used.\n     * @return digest_   The EIP-712 digest of the permit.\n     */\n    function _permitAndGetDigest(\n        address owner_,\n        address spender_,\n        uint256 amount_,\n        uint256 deadline_\n    ) internal virtual returns (bytes32 digest_) {\n        _revertIfExpired(deadline_);\n\n        _approve(owner_, spender_, amount_);\n\n        unchecked {\n            // Nonce realistically cannot overflow.\n            return\n                _getDigest(\n                    keccak256(abi.encode(PERMIT_TYPEHASH, owner_, spender_, amount_, nonces[owner_]++, deadline_))\n                );\n        }\n    }\n}\n"},{"file_path":"lib/common/src/Migratable.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IMigratable } from \"./interfaces/IMigratable.sol\";\n\n/**\n * @title  Abstract implementation for exposing the ability to migrate a contract, extending ERC-1967.\n * @author M^0 Labs\n */\nabstract contract Migratable is IMigratable {\n    /* ============ Variables ============ */\n\n    /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`.\n    uint256 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IMigratable\n    function migrate() external {\n        _migrate(_getMigrator());\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IMigratable\n    function implementation() public view returns (address implementation_) {\n        assembly {\n            implementation_ := sload(_IMPLEMENTATION_SLOT)\n        }\n    }\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @dev   Performs an arbitrary migration by delegate-calling `migrator_`.\n     * @param migrator_ The address of a migrator contract.\n     */\n    function _migrate(address migrator_) internal {\n        if (migrator_ == address(0)) revert ZeroMigrator();\n\n        if (migrator_.code.length == 0) revert InvalidMigrator();\n\n        address oldImplementation_ = implementation();\n\n        (bool success_, ) = migrator_.delegatecall(\"\");\n        if (!success_) revert MigrationFailed();\n\n        address newImplementation_ = implementation();\n\n        emit Migrated(migrator_, oldImplementation_, newImplementation_);\n\n        // NOTE: Redundant event emitted to conform to the EIP-1967 standard.\n        emit Upgraded(newImplementation_);\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /// @dev Returns the address of a migrator contract.\n    function _getMigrator() internal view virtual returns (address);\n}\n"},{"file_path":"lib/common/src/interfaces/IStatefulERC712.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IERC712Extended } from \"./IERC712Extended.sol\";\n\n/**\n * @title  Stateful Extension for EIP-712 typed structured data hashing and signing with nonces.\n * @author M^0 Labs\n */\ninterface IStatefulERC712 is IERC712Extended {\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when a signing account's nonce is not the expected current nonce.\n     * @param  nonce         The nonce used in the signature.\n     * @param  expectedNonce The expected nonce to be used in a signature by the signing account.\n     */\n    error InvalidAccountNonce(uint256 nonce, uint256 expectedNonce);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the next nonce to be used in a signature by `account`.\n     * @param  account The address of some account.\n     * @return nonce   The next nonce to be used in a signature by `account`.\n     */\n    function nonces(address account) external view returns (uint256 nonce);\n}\n"},{"file_path":"lib/common/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\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 IERC165 {\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[ERC 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":"lib/evm-m-extensions/src/components/forcedTransferable/ForcedTransferable.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.26;\n\nimport { AccessControlUpgradeable } from \"../../../lib/common/lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol\";\n\nimport { IForcedTransferable } from \"./IForcedTransferable.sol\";\n\n/**\n * @title  ForcedTransferable\n * @notice Upgradable contract that provides force transfer functionality.\n * @dev This contract is used to claw back funds from frozen accounts by authorized force transfer managers.\n * @author M0 Labs\n */\n\nabstract contract ForcedTransferable is IForcedTransferable, AccessControlUpgradeable {\n    /* ============ Variables ============ */\n\n    /// @inheritdoc IForcedTransferable\n    bytes32 public constant FORCED_TRANSFER_MANAGER_ROLE = keccak256(\"FORCED_TRANSFER_MANAGER_ROLE\");\n\n    /* ============ Initializer ============ */\n\n    /**\n     * @notice Initializes the contract with the given force transfer manager.\n     * @param forcedTransferManager The address of a force transfer manager.\n     */\n    function __ForcedTransferable_init(address forcedTransferManager) internal onlyInitializing {\n        if (forcedTransferManager == address(0)) revert ZeroForcedTransferManager();\n        _grantRole(FORCED_TRANSFER_MANAGER_ROLE, forcedTransferManager);\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IForcedTransferable\n    function forceTransfer(\n        address frozenAccount,\n        address recipient,\n        uint256 amount\n    ) external onlyRole(FORCED_TRANSFER_MANAGER_ROLE) {\n        _forceTransfer(frozenAccount, recipient, amount);\n    }\n\n    /// @inheritdoc IForcedTransferable\n    function forceTransfers(\n        address[] calldata frozenAccounts,\n        address[] calldata recipients,\n        uint256[] calldata amounts\n    ) external onlyRole(FORCED_TRANSFER_MANAGER_ROLE) {\n        uint256 len = frozenAccounts.length;\n        if (len != recipients.length || len != amounts.length) revert ArrayLengthMismatch();\n\n        for (uint256 i; i < len; ++i) {\n            _forceTransfer(frozenAccounts[i], recipients[i], amounts[i]);\n        }\n    }\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @dev   Internal ERC20 force transfer function to seize funds from a frozen account.\n     * @param frozenAccount The frozen account from which tokens are seized.\n     * @param recipient     The recipient's address.\n     * @param amount        The amount to be transferred.\n     */\n    function _forceTransfer(address frozenAccount, address recipient, uint256 amount) internal virtual {}\n}\n"},{"file_path":"lib/common/src/libs/SignatureChecker.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IERC1271 } from \"../interfaces/IERC1271.sol\";\n\n/**\n * @title  A library to handle ECDSA/secp256k1 and ERC1271 signatures, individually or in arbitrarily in combination.\n * @author M^0 Labs\n */\nlibrary SignatureChecker {\n    /* ============ Enums ============ */\n\n    /**\n     * @notice An enum representing the possible errors that can be emitted during signature validation.\n     * @param  NoError                No error occurred during signature validation.\n     * @param  InvalidSignature       The signature is invalid.\n     * @param  InvalidSignatureLength The signature length is invalid.\n     * @param  InvalidSignatureS      The signature parameter S is invalid.\n     * @param  InvalidSignatureV      The signature parameter V is invalid.\n     * @param  SignerMismatch         The signer does not match the recovered signer.\n     */\n    enum Error {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV,\n        SignerMismatch\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Returns whether a signature is valid (ECDSA/secp256k1 or ERC1271) for a signer and digest.\n     * @dev    Signatures must not be used as unique identifiers since the `ecrecover` EVM opcode\n     *         allows for malleable (non-unique) signatures.\n     *         See https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-4h98-2769-gh6h\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array signature.\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidSignature(address signer, bytes32 digest, bytes memory signature) internal view returns (bool) {\n        return isValidECDSASignature(signer, digest, signature) || isValidERC1271Signature(signer, digest, signature);\n    }\n\n    /**\n     * @dev    Returns whether an ERC1271 signature is valid for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ERC1271 signature.\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidERC1271Signature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal view returns (bool) {\n        (bool success_, bytes memory result_) = signer.staticcall(\n            abi.encodeCall(IERC1271.isValidSignature, (digest, signature))\n        );\n\n        return\n            success_ &&\n            result_.length >= 32 &&\n            abi.decode(result_, (bytes32)) == bytes32(IERC1271.isValidSignature.selector);\n    }\n\n    /**\n     * @dev    Decodes an ECDSA/secp256k1 signature from a byte array to standard v, r, and s parameters.\n     * @param  signature A byte array ECDSA/secp256k1 signature.\n     * @return v         An ECDSA/secp256k1 signature parameter.\n     * @return r         An ECDSA/secp256k1 signature parameter.\n     * @return s         An ECDSA/secp256k1 signature parameter.\n     */\n    function decodeECDSASignature(bytes memory signature) internal pure returns (uint8 v, bytes32 r, bytes32 s) {\n        // ecrecover takes the signature parameters, and they can be decoded using assembly.\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := mload(add(signature, 0x20))\n            s := mload(add(signature, 0x40))\n            v := byte(0, mload(add(signature, 0x60)))\n        }\n    }\n\n    /**\n     * @dev    Decodes an ECDSA/secp256k1 short signature as defined by EIP2098\n     *         from a byte array to standard v, r, and s parameters.\n     * @param  signature A byte array ECDSA/secp256k1 short signature.\n     * @return r         An ECDSA/secp256k1 signature parameter.\n     * @return vs        An ECDSA/secp256k1 short signature parameter.\n     */\n    function decodeShortECDSASignature(bytes memory signature) internal pure returns (bytes32 r, bytes32 vs) {\n        // ecrecover takes the signature parameters, and they can be decoded using assembly.\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := mload(add(signature, 0x20))\n            vs := mload(add(signature, 0x40))\n        }\n    }\n\n    /**\n     * @dev    Returns whether an ECDSA/secp256k1 signature is valid for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal pure returns (bool) {\n        if (signature.length == 64) {\n            (bytes32 r, bytes32 vs) = decodeShortECDSASignature(signature);\n            return isValidECDSASignature(signer, digest, r, vs);\n        }\n\n        return validateECDSASignature(signer, digest, signature) == Error.NoError;\n    }\n\n    /**\n     * @dev    Returns whether an ECDSA/secp256k1 short signature is valid for a signer and digest.\n     * @param  signer The address of the account purported to have signed.\n     * @param  digest The hash of the data that was signed.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  vs     An ECDSA/secp256k1 short signature parameter.\n     * @return        Whether the signature is valid or not.\n     */\n    function isValidECDSASignature(address signer, bytes32 digest, bytes32 r, bytes32 vs) internal pure returns (bool) {\n        return validateECDSASignature(signer, digest, r, vs) == Error.NoError;\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 signature for some digest.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ECDSA/secp256k1 signature.\n     * @return           An error, if any, that occurred during the signer recovery.\n     * @return           The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(bytes32 digest, bytes memory signature) internal pure returns (Error, address) {\n        if (signature.length != 65) return (Error.InvalidSignatureLength, address(0));\n\n        (uint8 v, bytes32 r, bytes32 s) = decodeECDSASignature(signature);\n\n        return recoverECDSASigner(digest, v, r, s);\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 short signature for some digest.\n     * @dev    See https://eips.ethereum.org/EIPS/eip-2098\n     * @param  digest The hash of the data that was signed.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  vs     An ECDSA/secp256k1 short signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     * @return        The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(bytes32 digest, bytes32 r, bytes32 vs) internal pure returns (Error, address) {\n        unchecked {\n            // We do not check for an overflow here since the shift operation results in 0 or 1.\n            uint8 v = uint8((uint256(vs) >> 255) + 27);\n            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n            return recoverECDSASigner(digest, v, r, s);\n        }\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 signature for some digest.\n     * @param  digest The hash of the data that was signed.\n     * @param  v      An ECDSA/secp256k1 signature parameter.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  s      An ECDSA/secp256k1 signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     * @return signer The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(\n        bytes32 digest,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (Error, address signer) {\n        // Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}.\n        if (uint256(s) > uint256(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0))\n            return (Error.InvalidSignatureS, address(0));\n\n        if (v != 27 && v != 28) return (Error.InvalidSignatureV, address(0));\n\n        signer = ecrecover(digest, v, r, s);\n\n        return (signer == address(0)) ? (Error.InvalidSignature, address(0)) : (Error.NoError, signer);\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 signature for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ERC1271 signature.\n     * @return           An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, signature);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 short signature for a signer and digest.\n     * @param  signer The address of the account purported to have signed.\n     * @param  digest The hash of the data that was signed.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  vs     An ECDSA/secp256k1 short signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, r, vs);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 signature for a signer and digest.\n     * @param  signer The address of the account purported to have signed.\n     * @param  digest The hash of the data that was signed.\n     * @param  v      An ECDSA/secp256k1 signature parameter.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  s      An ECDSA/secp256k1 signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, v, r, s);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error if `signer` is not `recoveredSigner`.\n     * @param  signer          The address of the some signer.\n     * @param  recoveredSigner The address of the some recoveredSigner.\n     * @return                 An error if `signer` is not `recoveredSigner`.\n     */\n    function validateRecoveredSigner(address signer, address recoveredSigner) internal pure returns (Error) {\n        return (signer == recoveredSigner) ? Error.NoError : Error.SignerMismatch;\n    }\n}\n"},{"file_path":"lib/common/src/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\n/**\n * @title  ERC20 Token Standard.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-20: https://eips.ethereum.org/EIPS/eip-20\n */\ninterface IERC20 {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when `spender` has been approved for `amount` of the token balance of `account`.\n     * @param  account The address of the account.\n     * @param  spender The address of the spender being approved for the allowance.\n     * @param  amount  The amount of the allowance being approved.\n     */\n    event Approval(address indexed account, address indexed spender, uint256 amount);\n\n    /**\n     * @notice Emitted when `amount` tokens is transferred from `sender` to `recipient`.\n     * @param  sender    The address of the sender who's token balance is decremented.\n     * @param  recipient The address of the recipient who's token balance is incremented.\n     * @param  amount    The amount of tokens being transferred.\n     */\n    event Transfer(address indexed sender, address indexed recipient, uint256 amount);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Allows a calling account to approve `spender` to spend up to `amount` of its token balance.\n     * @dev    MUST emit an `Approval` event.\n     * @param  spender The address of the account being allowed to spend up to the allowed amount.\n     * @param  amount  The amount of the allowance being approved.\n     * @return Whether or not the approval was successful.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @notice Allows a calling account to transfer `amount` tokens to `recipient`.\n     * @param  recipient The address of the recipient who's token balance will be incremented.\n     * @param  amount    The amount of tokens being transferred.\n     * @return Whether or not the transfer was successful.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @notice Allows a calling account to transfer `amount` tokens from `sender`, with allowance, to a `recipient`.\n     * @param  sender    The address of the sender who's token balance will be decremented.\n     * @param  recipient The address of the recipient who's token balance will be incremented.\n     * @param  amount    The amount of tokens being transferred.\n     * @return Whether or not the transfer was successful.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the allowance `spender` is allowed to spend on behalf of `account`.\n     * @param  account The address of the account who's token balance `spender` is allowed to spend.\n     * @param  spender The address of an account allowed to spend on behalf of `account`.\n     * @return The amount `spender` can spend on behalf of `account`.\n     */\n    function allowance(address account, address spender) external view returns (uint256);\n\n    /**\n     * @notice Returns the token balance of `account`.\n     * @param  account The address of some account.\n     * @return The token balance of `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /// @notice Returns the number of decimals UIs should assume all amounts have.\n    function decimals() external view returns (uint8);\n\n    /// @notice Returns the name of the contract/token.\n    function name() external view returns (string memory);\n\n    /// @notice Returns the symbol of the token.\n    function symbol() external view returns (string memory);\n\n    /// @notice Returns the current total supply of the token.\n    function totalSupply() external view returns (uint256);\n}\n"},{"file_path":"lib/common/src/libs/IndexingMath.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { UIntMath } from \"./UIntMath.sol\";\n\n/**\n * @title  Helper library for indexing math functions.\n * @author M^0 Labs\n */\nlibrary IndexingMath {\n    /* ============ Variables ============ */\n\n    /// @notice The scaling of indexes for exponent math.\n    uint56 internal constant EXP_SCALED_ONE = 1e12;\n\n    /* ============ Custom Errors ============ */\n\n    /// @notice Emitted when a division by zero occurs.\n    error DivisionByZero();\n\n    /* ============ Exposed Functions ============ */\n\n    /**\n     * @notice Helper function to calculate `(x * EXP_SCALED_ONE) / y`, rounded down.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function divide240By128Down(uint240 x, uint128 y) internal pure returns (uint112) {\n        if (y == 0) revert DivisionByZero();\n\n        unchecked {\n            // NOTE: While `uint256(x) * EXP_SCALED_ONE` can technically overflow, these divide/multiply functions are\n            //       only used for the purpose of principal/present amount calculations for continuous indexing, and\n            //       so for an `x` to be large enough to overflow this, it would have to be a possible result of\n            //       `multiply112By128Down` or `multiply112By128Up`, which would already satisfy\n            //       `uint256(x) * EXP_SCALED_ONE < type(uint240).max`.\n            return UIntMath.safe112((uint256(x) * EXP_SCALED_ONE) / y);\n        }\n    }\n\n    /**\n     * @notice Helper function to calculate `(x * EXP_SCALED_ONE) / y`, rounded up.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function divide240By128Up(uint240 x, uint128 y) internal pure returns (uint112) {\n        if (y == 0) revert DivisionByZero();\n\n        unchecked {\n            // NOTE: While `uint256(x) * EXP_SCALED_ONE` can technically overflow, these divide/multiply functions are\n            //       only used for the purpose of principal/present amount calculations for continuous indexing, and\n            //       so for an `x` to be large enough to overflow this, it would have to be a possible result of\n            //       `multiply112By128Down` or `multiply112By128Up`, which would already satisfy\n            //       `uint256(x) * EXP_SCALED_ONE < type(uint240).max`.\n            return UIntMath.safe112(((uint256(x) * EXP_SCALED_ONE) + y - 1) / y);\n        }\n    }\n\n    /**\n     * @notice Helper function to calculate `(x * y) / EXP_SCALED_ONE`, rounded down.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function multiply112By128Down(uint112 x, uint128 y) internal pure returns (uint240) {\n        unchecked {\n            return uint240((uint256(x) * y) / EXP_SCALED_ONE);\n        }\n    }\n\n    /**\n     * @notice Helper function to calculate `(x * index) / EXP_SCALED_ONE`, rounded up.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function multiply112By128Up(uint112 x, uint128 index) internal pure returns (uint240 z) {\n        unchecked {\n            return uint240(((uint256(x) * index) + (EXP_SCALED_ONE - 1)) / EXP_SCALED_ONE);\n        }\n    }\n\n    /**\n     * @dev    Returns the present amount (rounded down) given the principal amount and an index.\n     * @param  principalAmount The principal amount.\n     * @param  index           An index.\n     * @return The present amount rounded down.\n     */\n    function getPresentAmountRoundedDown(uint112 principalAmount, uint128 index) internal pure returns (uint240) {\n        return multiply112By128Down(principalAmount, index);\n    }\n\n    /**\n     * @dev    Returns the present amount (rounded up) given the principal amount and an index.\n     * @param  principalAmount The principal amount.\n     * @param  index           An index.\n     * @return The present amount rounded up.\n     */\n    function getPresentAmountRoundedUp(uint112 principalAmount, uint128 index) internal pure returns (uint240) {\n        return multiply112By128Up(principalAmount, index);\n    }\n\n    /**\n     * @dev    Returns the principal amount given the present amount, using the current index.\n     * @param  presentAmount The present amount.\n     * @param  index         An index.\n     * @return The principal amount rounded down.\n     */\n    function getPrincipalAmountRoundedDown(uint240 presentAmount, uint128 index) internal pure returns (uint112) {\n        return divide240By128Down(presentAmount, index);\n    }\n\n    /**\n     * @dev    Returns the principal amount given the present amount, using the current index.\n     * @param  presentAmount The present amount.\n     * @param  index         An index.\n     * @return The principal amount rounded up.\n     */\n    function getPrincipalAmountRoundedUp(uint240 presentAmount, uint128 index) internal pure returns (uint112) {\n        return divide240By128Up(presentAmount, index);\n    }\n}\n"},{"file_path":"src/interfaces/ISwapFacilityLike.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.26;\n\n/**\n * @title  Subset of SwapFacility interface.\n * @author M0 Labs\n */\ninterface ISwapFacilityLike {\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Swaps $M token to $M Extension.\n     * @param  extensionOut The address of the M Extension to swap to.\n     * @param  amount       The amount of $M token to swap.\n     * @param  recipient    The address to receive the swapped $M Extension tokens.\n     */\n    function swapInM(address extensionOut, uint256 amount, address recipient) external;\n\n    /**\n     * @notice Swaps $M Extension to $M token.\n     * @param  extensionIn The address of the $M Extension to swap from.\n     * @param  amount      The amount of $M Extension tokens to swap.\n     * @param  recipient   The address to receive $M tokens.\n     */\n    function swapOutM(address extensionIn, uint256 amount, address recipient) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the address that called `swap` or `swapM`\n     * @dev    Must be used instead of `msg.sender` in $M Extensions contracts to get the original sender.\n     * @return The address of the original message sender.\n     */\n    function msgSender() external view returns (address);\n}\n"},{"file_path":"lib/common/src/libs/UIntMath.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\n/**\n * @title  Library to perform safe math operations on uint types\n * @author M^0 Labs\n */\nlibrary UIntMath {\n    /* ============ Custom Errors ============ */\n\n    /// @notice Emitted when a passed value is greater than the maximum value of uint16.\n    error InvalidUInt16();\n\n    /// @notice Emitted when a passed value is greater than the maximum value of uint32.\n    error InvalidUInt32();\n\n    /// @notice Emitted when a passed value is greater than the maximum value of uint40.\n    error InvalidUInt40();\n\n    /// @notice Emitted when a passed value is greater than the maximum value of uint48.\n    error InvalidUInt48();\n\n    /// @notice Emitted when a passed value is greater than the maximum value of uint112.\n    error InvalidUInt112();\n\n    /// @notice Emitted when a passed value is greater than the maximum value of uint128.\n    error InvalidUInt128();\n\n    /// @notice Emitted when a passed value is greater than the maximum value of uint240.\n    error InvalidUInt240();\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @notice Casts a uint256 value to a uint16, ensuring that it is less than or equal to the maximum uint16 value.\n     * @param  n The value to cast.\n     * @return The value casted to uint16.\n     */\n    function safe16(uint256 n) internal pure returns (uint16) {\n        if (n > type(uint16).max) revert InvalidUInt16();\n        return uint16(n);\n    }\n\n    /**\n     * @notice Casts a uint256 value to a uint32, ensuring that it is less than or equal to the maximum uint32 value.\n     * @param  n The value to cast.\n     * @return The value casted to uint32.\n     */\n    function safe32(uint256 n) internal pure returns (uint32) {\n        if (n > type(uint32).max) revert InvalidUInt32();\n        return uint32(n);\n    }\n\n    /**\n     * @notice Casts a uint256 value to a uint40, ensuring that it is less than or equal to the maximum uint40 value.\n     * @param  n The value to cast.\n     * @return The value casted to uint40.\n     */\n    function safe40(uint256 n) internal pure returns (uint40) {\n        if (n > type(uint40).max) revert InvalidUInt40();\n        return uint40(n);\n    }\n\n    /**\n     * @notice Casts a uint256 value to a uint48, ensuring that it is less than or equal to the maximum uint48 value.\n     * @param  n The value to cast.\n     * @return The value casted to uint48.\n     */\n    function safe48(uint256 n) internal pure returns (uint48) {\n        if (n > type(uint48).max) revert InvalidUInt48();\n        return uint48(n);\n    }\n\n    /**\n     * @notice Casts a uint256 value to a uint112, ensuring that it is less than or equal to the maximum uint112 value.\n     * @param  n The value to cast.\n     * @return The value casted to uint112.\n     */\n    function safe112(uint256 n) internal pure returns (uint112) {\n        if (n > type(uint112).max) revert InvalidUInt112();\n        return uint112(n);\n    }\n\n    /**\n     * @notice Casts a uint256 value to a uint128, ensuring that it is less than or equal to the maximum uint128 value.\n     * @param  n The value to cast.\n     * @return The value casted to uint128.\n     */\n    function safe128(uint256 n) internal pure returns (uint128) {\n        if (n > type(uint128).max) revert InvalidUInt128();\n        return uint128(n);\n    }\n\n    /**\n     * @notice Casts a uint256 value to a uint240, ensuring that it is less than or equal to the maximum uint240 value.\n     * @param  n The value to cast.\n     * @return The value casted to uint240.\n     */\n    function safe240(uint256 n) internal pure returns (uint240) {\n        if (n > type(uint240).max) revert InvalidUInt240();\n        return uint240(n);\n    }\n\n    /**\n     * @notice Limits a uint256 value to the maximum uint32 value.\n     * @param  n The value to bound.\n     * @return The value limited to within uint32 bounds.\n     */\n    function bound32(uint256 n) internal pure returns (uint32) {\n        return uint32(min256(n, uint256(type(uint32).max)));\n    }\n\n    /**\n     * @notice Limits a uint256 value to the maximum uint112 value.\n     * @param  n The value to bound.\n     * @return The value limited to within uint112 bounds.\n     */\n    function bound112(uint256 n) internal pure returns (uint112) {\n        return uint112(min256(n, uint256(type(uint112).max)));\n    }\n\n    /**\n     * @notice Limits a uint256 value to the maximum uint128 value.\n     * @param  n The value to bound.\n     * @return The value limited to within uint128 bounds.\n     */\n    function bound128(uint256 n) internal pure returns (uint128) {\n        return uint128(min256(n, uint256(type(uint128).max)));\n    }\n\n    /**\n     * @notice Limits a uint256 value to the maximum uint240 value.\n     * @param  n The value to bound.\n     * @return The value limited to within uint240 bounds.\n     */\n    function bound240(uint256 n) internal pure returns (uint240) {\n        return uint240(min256(n, uint256(type(uint240).max)));\n    }\n\n    /**\n     * @notice Compares two uint32 values and returns the larger one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The larger value.\n     */\n    function max32(uint32 a, uint32 b) internal pure returns (uint32) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @notice Compares two uint40 values and returns the larger one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The larger value.\n     */\n    function max40(uint40 a, uint40 b) internal pure returns (uint40) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @notice Compares two uint128 values and returns the larger one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The larger value.\n     */\n    function max128(uint128 a, uint128 b) internal pure returns (uint128) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @notice Compares two uint240 values and returns the larger one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The larger value.\n     */\n    function max240(uint240 a, uint240 b) internal pure returns (uint240) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @notice Compares two uint32 values and returns the lesser one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The lesser value.\n     */\n    function min32(uint32 a, uint32 b) internal pure returns (uint32) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @notice Compares two uint40 values and returns the lesser one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The lesser value.\n     */\n    function min40(uint40 a, uint40 b) internal pure returns (uint40) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @notice Compares two uint240 values and returns the lesser one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The lesser value.\n     */\n    function min240(uint240 a, uint240 b) internal pure returns (uint240) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @notice Compares two uint112 values and returns the lesser one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The lesser value.\n     */\n    function min112(uint112 a, uint112 b) internal pure returns (uint112) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @notice Compares two uint256 values and returns the lesser one.\n     * @param  a Value to compare.\n     * @param  b Value to compare.\n     * @return The lesser value.\n     */\n    function min256(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n}\n"},{"file_path":"lib/common/src/ERC712Extended.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IERC712 } from \"./interfaces/IERC712.sol\";\nimport { IERC712Extended } from \"./interfaces/IERC712Extended.sol\";\n\nimport { Bytes32String } from \"./libs/Bytes32String.sol\";\nimport { SignatureChecker } from \"./libs/SignatureChecker.sol\";\n\n/**\n * @title  Typed structured data hashing and signing via EIP-712, extended by EIP-5267.\n * @author M^0 Labs\n * @dev    An abstract implementation to satisfy EIP-712: https://eips.ethereum.org/EIPS/eip-712\n */\nabstract contract ERC712Extended is IERC712Extended {\n    /* ============ Variables ============ */\n\n    /// @dev keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")\n    bytes32 internal constant _EIP712_DOMAIN_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\n\n    /// @dev keccak256(\"1\")\n    bytes32 internal constant _EIP712_VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;\n\n    /// @dev Initial Chain ID set at deployment.\n    uint256 internal immutable _INITIAL_CHAIN_ID;\n\n    /// @dev Initial EIP-712 domain separator set at deployment.\n    bytes32 internal immutable _INITIAL_DOMAIN_SEPARATOR;\n\n    /// @dev Initial address of this contract set at deployment, used to detect proxy (delegatecall) context.\n    address internal immutable _INITIAL_THIS;\n\n    /// @dev The name of the contract (stored as a bytes32 instead of a string in order to be immutable).\n    bytes32 internal immutable _name;\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Constructs the EIP-712 domain separator.\n     * @param  name_ The name of the contract.\n     */\n    constructor(string memory name_) {\n        _name = Bytes32String.toBytes32(name_);\n\n        _INITIAL_CHAIN_ID = block.chainid;\n        _INITIAL_THIS = address(this);\n        _INITIAL_DOMAIN_SEPARATOR = _getDomainSeparator();\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IERC712Extended\n    function eip712Domain()\n        external\n        view\n        virtual\n        returns (\n            bytes1 fields_,\n            string memory name_,\n            string memory version_,\n            uint256 chainId_,\n            address verifyingContract_,\n            bytes32 salt_,\n            uint256[] memory extensions_\n        )\n    {\n        return (\n            hex\"0f\", // 01111\n            Bytes32String.toString(_name),\n            \"1\",\n            block.chainid,\n            address(this),\n            bytes32(0),\n            new uint256[](0)\n        );\n    }\n\n    /// @inheritdoc IERC712\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return\n            (address(this) == _INITIAL_THIS && block.chainid == _INITIAL_CHAIN_ID)\n                ? _INITIAL_DOMAIN_SEPARATOR\n                : _getDomainSeparator();\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Computes the EIP-712 domain separator.\n     * @return The EIP-712 domain separator.\n     */\n    function _getDomainSeparator() internal view returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    _EIP712_DOMAIN_HASH,\n                    keccak256(bytes(Bytes32String.toString(_name))),\n                    _EIP712_VERSION_HASH,\n                    block.chainid,\n                    address(this)\n                )\n            );\n    }\n\n    /**\n     * @dev    Returns the digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  internalDigest_ The internal digest.\n     * @return The digest to be signed.\n     */\n    function _getDigest(bytes32 internalDigest_) internal view returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR(), internalDigest_));\n    }\n\n    /**\n     * @dev   Revert if the signature is expired.\n     * @param expiry_ Timestamp at which the signature expires or max uint256 for no expiry.\n     */\n    function _revertIfExpired(uint256 expiry_) internal view {\n        if (block.timestamp > expiry_) revert SignatureExpired(expiry_, block.timestamp);\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @dev   We first validate if the signature is a valid ECDSA signature and return early if it is the case.\n     *        Then, we validate if it is a valid ERC-1271 signature, and return early if it is the case.\n     *        If not, we revert with the error from the ECDSA signature validation.\n     * @param signer_    The signer of the signature.\n     * @param digest_    The digest that was signed.\n     * @param signature_ The signature.\n     */\n    function _revertIfInvalidSignature(address signer_, bytes32 digest_, bytes memory signature_) internal view {\n        SignatureChecker.Error error_ = SignatureChecker.validateECDSASignature(signer_, digest_, signature_);\n\n        if (error_ == SignatureChecker.Error.NoError) return;\n\n        if (SignatureChecker.isValidERC1271Signature(signer_, digest_, signature_)) return;\n\n        _revertIfError(error_);\n    }\n\n    /**\n     * @dev    Returns the signer of a signed digest, via EIP-712, and reverts if the signature is invalid.\n     * @param  digest_ The digest that was signed.\n     * @param  v_      v of the signature.\n     * @param  r_      r of the signature.\n     * @param  s_      s of the signature.\n     * @return signer_ The signer of the digest.\n     */\n    function _getSignerAndRevertIfInvalidSignature(\n        bytes32 digest_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) internal pure returns (address signer_) {\n        SignatureChecker.Error error_;\n\n        (error_, signer_) = SignatureChecker.recoverECDSASigner(digest_, v_, r_, s_);\n\n        _revertIfError(error_);\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @param signer_ The signer of the signature.\n     * @param digest_ The digest that was signed.\n     * @param r_      An ECDSA/secp256k1 signature parameter.\n     * @param vs_     An ECDSA/secp256k1 short signature parameter.\n     */\n    function _revertIfInvalidSignature(address signer_, bytes32 digest_, bytes32 r_, bytes32 vs_) internal pure {\n        _revertIfError(SignatureChecker.validateECDSASignature(signer_, digest_, r_, vs_));\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @param signer_ The signer of the signature.\n     * @param digest_ The digest that was signed.\n     * @param v_      v of the signature.\n     * @param r_      r of the signature.\n     * @param s_      s of the signature.\n     */\n    function _revertIfInvalidSignature(\n        address signer_,\n        bytes32 digest_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) internal pure {\n        _revertIfError(SignatureChecker.validateECDSASignature(signer_, digest_, v_, r_, s_));\n    }\n\n    /**\n     * @dev   Revert if error.\n     * @param error_ The SignatureChecker Error enum.\n     */\n    function _revertIfError(SignatureChecker.Error error_) private pure {\n        if (error_ == SignatureChecker.Error.NoError) return;\n        if (error_ == SignatureChecker.Error.InvalidSignature) revert InvalidSignature();\n        if (error_ == SignatureChecker.Error.InvalidSignatureLength) revert InvalidSignatureLength();\n        if (error_ == SignatureChecker.Error.InvalidSignatureS) revert InvalidSignatureS();\n        if (error_ == SignatureChecker.Error.InvalidSignatureV) revert InvalidSignatureV();\n        if (error_ == SignatureChecker.Error.SignerMismatch) revert SignerMismatch();\n\n        revert InvalidSignature();\n    }\n}\n"},{"file_path":"lib/common/src/interfaces/IERC3009.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IStatefulERC712 } from \"./IStatefulERC712.sol\";\n\n/**\n * @title  Transfer via signed authorization following EIP-3009 standard.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-3009: https://eips.ethereum.org/EIPS/eip-3009\n */\ninterface IERC3009 is IStatefulERC712 {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when an authorization has been canceled.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the canceled authorization.\n     */\n    event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce);\n\n    /**\n     * @notice Emitted when an authorization has been used.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the used authorization.\n     */\n    event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);\n\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Emitted when an authorization has already been used.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the used authorization.\n     */\n    error AuthorizationAlreadyUsed(address authorizer, bytes32 nonce);\n\n    /**\n     * @notice Emitted when an authorization is expired.\n     * @param  timestamp   Timestamp at which the transaction was submitted.\n     * @param  validBefore Timestamp before which the authorization would have been valid.\n     */\n    error AuthorizationExpired(uint256 timestamp, uint256 validBefore);\n\n    /**\n     * @notice Emitted when an authorization is not yet valid.\n     * @param  timestamp  Timestamp at which the transaction was submitted.\n     * @param  validAfter Timestamp after which the authorization will be valid.\n     */\n    error AuthorizationNotYetValid(uint256 timestamp, uint256 validAfter);\n\n    /**\n     * @notice Emitted when the caller of `receiveWithAuthorization` is not the payee.\n     * @param  caller Caller's address.\n     * @param  payee  Payee's address.\n     */\n    error CallerMustBePayee(address caller, address payee);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  signature   A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes memory signature\n    ) external;\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  r           An ECDSA/secp256k1 signature parameter.\n     * @param  vs          An ECDSA/secp256k1 short signature parameter.\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes32 r,\n        bytes32 vs\n    ) external;\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  v           v of the signature.\n     * @param  r           r of the signature.\n     * @param  s           s of the signature.\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  signature   A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes memory signature\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  r           An ECDSA/secp256k1 signature parameter.\n     * @param  vs          An ECDSA/secp256k1 short signature parameter.\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes32 r,\n        bytes32 vs\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  v           v of the signature.\n     * @param  r           r of the signature.\n     * @param  s           s of the signature.\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  signature  A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  r          An ECDSA/secp256k1 signature parameter.\n     * @param  vs         An ECDSA/secp256k1 short signature parameter.\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, bytes32 r, bytes32 vs) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  v          v of the signature.\n     * @param  r          r of the signature.\n     * @param  s          s of the signature.\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the state of an authorization.\n     * @dev    Nonces are randomly generated 32-byte data unique to the authorizer's address\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @return True if the nonce is used.\n     */\n    function authorizationState(address authorizer, bytes32 nonce) external view returns (bool);\n\n    /// @notice Returns `transferWithAuthorization` typehash.\n    function TRANSFER_WITH_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n\n    /// @notice Returns `receiveWithAuthorization` typehash.\n    function RECEIVE_WITH_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n\n    /// @notice Returns `cancelAuthorization` typehash.\n    function CANCEL_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n}\n"},{"file_path":"lib/common/src/interfaces/IERC1271.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\n/**\n * @title  Standard Signature Validation Method for Contracts via EIP-1271.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-1271: https://eips.ethereum.org/EIPS/eip-1271\n */\ninterface IERC1271 {\n    /**\n     * @dev    Returns a specific magic value if the provided signature is valid for the provided digest.\n     * @param  digest     Hash of the data purported to have been signed.\n     * @param  signature  Signature byte array associated with the digest.\n     * @return magicValue Magic value 0x1626ba7e if the signature is valid.\n     */\n    function isValidSignature(bytes32 digest, bytes memory signature) external view returns (bytes4 magicValue);\n}\n"},{"file_path":"lib/evm-m-extensions/src/components/freezable/Freezable.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.26;\n\nimport { AccessControlUpgradeable } from \"../../../lib/common/lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol\";\n\nimport { IFreezable } from \"./IFreezable.sol\";\n\nabstract contract FreezableStorageLayout {\n    /// @custom:storage-location erc7201:M0.storage.Freezable\n    struct FreezableStorageStruct {\n        mapping(address account => bool isFrozen) isFrozen;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"M0.storage.Freezable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant _FREEZABLE_STORAGE_LOCATION =\n        0x2fd5767309dce890c526ace85d7fe164825199d7dcd99c33588befc51b32ce00;\n\n    function _getFreezableStorageLocation() internal pure returns (FreezableStorageStruct storage $) {\n        assembly {\n            $.slot := _FREEZABLE_STORAGE_LOCATION\n        }\n    }\n}\n\n/**\n * @title Freezable\n * @notice Upgradeable contract that allows for the freezing of accounts.\n * @dev This contract is used to prevent certain accounts from interacting with the contract.\n * @author M0 Labs\n */\nabstract contract Freezable is IFreezable, FreezableStorageLayout, AccessControlUpgradeable {\n    /* ============ Variables ============ */\n\n    /// @inheritdoc IFreezable\n    bytes32 public constant FREEZE_MANAGER_ROLE = keccak256(\"FREEZE_MANAGER_ROLE\");\n\n    /* ============ Initializer ============ */\n\n    /**\n     * @notice Initializes the contract with the given freeze manager.\n     * @param freezeManager The address of a freeze manager.\n     */\n    function __Freezable_init(address freezeManager) internal onlyInitializing {\n        if (freezeManager == address(0)) revert ZeroFreezeManager();\n        _grantRole(FREEZE_MANAGER_ROLE, freezeManager);\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IFreezable\n    function freeze(address account) external virtual onlyRole(FREEZE_MANAGER_ROLE) {\n        _freeze(_getFreezableStorageLocation(), account);\n    }\n\n    /// @inheritdoc IFreezable\n    function freezeAccounts(address[] calldata accounts) external virtual onlyRole(FREEZE_MANAGER_ROLE) {\n        FreezableStorageStruct storage $ = _getFreezableStorageLocation();\n        for (uint256 i; i < accounts.length; ++i) {\n            _freeze($, accounts[i]);\n        }\n    }\n\n    /// @inheritdoc IFreezable\n    function unfreeze(address account) external onlyRole(FREEZE_MANAGER_ROLE) {\n        _unfreeze(_getFreezableStorageLocation(), account);\n    }\n\n    /// @inheritdoc IFreezable\n    function unfreezeAccounts(address[] calldata accounts) external onlyRole(FREEZE_MANAGER_ROLE) {\n        FreezableStorageStruct storage $ = _getFreezableStorageLocation();\n\n        for (uint256 i; i < accounts.length; ++i) {\n            _unfreeze($, accounts[i]);\n        }\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IFreezable\n    function isFrozen(address account) public view returns (bool) {\n        return _getFreezableStorageLocation().isFrozen[account];\n    }\n\n    /* ============ Hooks For Internal Interactive Functions ============ */\n\n    /**\n     * @dev   Hook called before freezing an account.\n     * @param account   The account to be frozen.\n     */\n    function _beforeFreeze(address account) internal virtual {}\n\n    /**\n     * @dev    Hook called before unfreezing an account.\n     * @param  account   The account to be unfrozen.\n     */\n    function _beforeUnfreeze(address account) internal virtual {}\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @notice Internal function that freezes an account.\n     * @param $ The storage location of the freezable contract.\n     * @param account The account to freeze.\n     */\n    function _freeze(FreezableStorageStruct storage $, address account) internal {\n        // Return early if the account is already frozen\n        if ($.isFrozen[account]) return;\n\n        _beforeFreeze(account);\n\n        $.isFrozen[account] = true;\n\n        emit Frozen(account, block.timestamp);\n    }\n\n    /**\n     * @notice Internal function that unfreezes an account.\n     * @param $ The storage location of the freezable contract.\n     * @param account The account to unfreeze.\n     */\n    function _unfreeze(FreezableStorageStruct storage $, address account) internal {\n        // Return early if the account is not frozen\n        if (!$.isFrozen[account]) return;\n\n        _beforeUnfreeze(account);\n\n        $.isFrozen[account] = false;\n\n        emit Unfrozen(account, block.timestamp);\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @notice Internal function that reverts if an account is frozen.\n     * @dev Called by inheriting contracts to check if an account is frozen.\n     * @param $ The storage location of the freezable contract.\n     * @param account The account to check.\n     */\n    function _revertIfFrozen(FreezableStorageStruct storage $, address account) internal view {\n        if ($.isFrozen[account]) revert AccountFrozen(account);\n    }\n\n    /**\n     * @notice Internal function that reverts if an account is frozen.\n     * @dev Called by inheriting contracts to check if an account is frozen.\n     * @param account The account to check.\n     */\n    function _revertIfFrozen(address account) internal view {\n        if (_getFreezableStorageLocation().isFrozen[account]) revert AccountFrozen(account);\n    }\n\n    /**\n     * @notice Internal function that reverts if an account is not frozen.\n     * @dev Called by inheriting contracts to check if an account is not frozen.\n     * @param $ The storage location of the freezable contract.\n     * @param account The account to check.\n     */\n    function _revertIfNotFrozen(FreezableStorageStruct storage $, address account) internal view {\n        if (!$.isFrozen[account]) revert AccountNotFrozen(account);\n    }\n\n    /**\n     * @notice Internal function that reverts if an account is not frozen.\n     * @dev Called by inheriting contracts to check if an account is not frozen.\n     * @param account The account to check.\n     */\n    function _revertIfNotFrozen(address account) internal view {\n        if (!_getFreezableStorageLocation().isFrozen[account]) revert AccountNotFrozen(account);\n    }\n}\n"},{"file_path":"lib/evm-m-extensions/src/components/pausable/IPausable.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.26;\n\n/**\n * @title Pausable interface.\n * @author M0 Labs\n */\ninterface IPausable {\n    /* ============ Errors ============ */\n\n    /// @notice Emitted if no pauser is set.\n    error ZeroPauser();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Pauses the contract.\n     * @dev    Can only be called by an account with the PAUSER_ROLE.\n     * @dev    When paused, wrap/unwrap and transfer of tokens should be disabled.\n     *         Approval should still be enabled to allow users to change their allowances.\n     */\n    function pause() external;\n\n    /**\n     * @notice Unpauses the contract.\n     * @dev    Can only be called by an account with the PAUSER_ROLE.\n     */\n    function unpause() external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice The role that can pause/unpause the contract.\n    function PAUSER_ROLE() external view returns (bytes32);\n}\n"},{"file_path":"src/interfaces/IRegistrarLike.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.26;\n\n/**\n * @title  Subset of Registrar interface required for source contracts.\n * @author M0 Labs\n */\ninterface IRegistrarLike {\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the value of `key`.\n     * @param  key   Some key.\n     * @return value Some value.\n     */\n    function get(bytes32 key) external view returns (bytes32 value);\n\n    /**\n     * @notice Returns whether `list` contains `account` or not.\n     * @param  list     The key for some list.\n     * @param  account  The address of some account.\n     * @return contains Whether `list` contains `account` or not.\n     */\n    function listContains(bytes32 list, address account) external view returns (bool contains);\n}\n"},{"file_path":"lib/evm-m-extensions/lib/common/lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165 {\n    function __ERC165_init() internal onlyInitializing {\n    }\n\n    function __ERC165_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"lib/common/src/interfaces/IMigratable.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\n/**\n * @title  Interface for exposing the ability to migrate a contract, extending the ERC-1967 interface.\n * @author M^0 Labs\n */\ninterface IMigratable {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when a migration to a new implementation is performed.\n     * @param  migrator          The address that performed the migration.\n     * @param  oldImplementation The address of the old implementation.\n     * @param  newImplementation The address of the new implementation.\n     */\n    event Migrated(address indexed migrator, address indexed oldImplementation, address indexed newImplementation);\n\n    /**\n     * @notice Emitted when the implementation address for the proxy is changed.\n     * @param  implementation The address of the new implementation for the proxy.\n     */\n    event Upgraded(address indexed implementation);\n\n    /// @notice Emitted when calling `stopEarning` for an account approved as earner by the Registrar.\n    error InvalidMigrator();\n\n    /// @notice Emitted when the delegatecall to a migrator fails.\n    error MigrationFailed();\n\n    /// @notice Emitted when the zero address is passed as a migrator.\n    error ZeroMigrator();\n\n    /* ============ Interactive Functions ============ */\n\n    /// @notice Performs an arbitrarily defined migration.\n    function migrate() external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the address of the current implementation contract.\n    function implementation() external view returns (address);\n}\n"},{"file_path":"lib/evm-m-extensions/src/components/forcedTransferable/IForcedTransferable.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.26;\n\ninterface IForcedTransferable {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when tokens are forcefully transferred from a frozen account.\n     */\n    event ForcedTransfer(\n        address indexed frozenAccount,\n        address indexed recipient,\n        address indexed forcedTransferManager,\n        uint256 amount\n    );\n\n    /* ============ Custom Errors ============ */\n\n    /// @notice Error for zero forced transfer manager address\n    error ZeroForcedTransferManager();\n\n    /// @notice Error for array length mismatch\n    error ArrayLengthMismatch();\n\n    /* ============ Interactive Functions ============ */\n    /**\n     * @notice Forcefully transfers tokens from a frozen account to a recipient.\n     * @dev    MUST only be callable by the FORCE_TRANSFER_MANAGER_ROLE.\n     * @dev    SHOULD revert if `frozenAccount` is not frozen.\n     * @dev    SHOULD revert if `recipient` is the zero address.\n     * @dev    SHOULD revert if `amount` exceeds the balance of `frozenAccount`.\n     * @param  frozenAccount The address of the frozen account from which tokens are seized.\n     * @param  recipient     The address receiving the seized tokens.\n     * @param  amount        The amount of tokens to transfer.\n     */\n    function forceTransfer(address frozenAccount, address recipient, uint256 amount) external;\n\n    /**\n     * @notice Forcefully transfers tokens from multiple frozen accounts to multiple recipients.\n     * @dev    MUST only be callable by the FORCE_TRANSFER_MANAGER_ROLE.\n     * @dev    SHOULD revert if any `frozenAccount` is not frozen.\n     * @dev    SHOULD revert if array lengths do not match.\n     * @dev    SHOULD revert if any `recipient` is the zero address.\n     * @dev    SHOULD revert if any `amount` exceeds the balance of the corresponding `frozenAccount`.\n     * @param  frozenAccounts The array of frozen accounts from which tokens are seized.\n     * @param  recipients     The array of recipient addresses.\n     * @param  amounts        The array of amounts to transfer for each account.\n     */\n    function forceTransfers(\n        address[] calldata frozenAccounts,\n        address[] calldata recipients,\n        uint256[] calldata amounts\n    ) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice The role that can manage force transfers.\n    function FORCED_TRANSFER_MANAGER_ROLE() external view returns (bytes32);\n}\n"},{"file_path":"lib/common/src/interfaces/IERC712.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\n/**\n * @title  Typed structured data hashing and signing via EIP-712.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-712: https://eips.ethereum.org/EIPS/eip-712\n */\ninterface IERC712 {\n    /* ============ Custom Errors ============ */\n\n    /// @notice Revert message when an invalid signature is detected.\n    error InvalidSignature();\n\n    /// @notice Revert message when a signature with invalid length is detected.\n    error InvalidSignatureLength();\n\n    /// @notice Revert message when the S portion of a signature is invalid.\n    error InvalidSignatureS();\n\n    /// @notice Revert message when the V portion of a signature is invalid.\n    error InvalidSignatureV();\n\n    /**\n     * @notice Revert message when a signature is being used beyond its deadline (i.e. expiry).\n     * @param  deadline  The last timestamp where the signature is still valid.\n     * @param  timestamp The current timestamp.\n     */\n    error SignatureExpired(uint256 deadline, uint256 timestamp);\n\n    /// @notice Revert message when a recovered signer does not match the account being purported to have signed.\n    error SignerMismatch();\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the EIP712 domain separator used in the encoding of a signed digest.\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"},{"file_path":"lib/common/src/StatefulERC712.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.8.20 <0.9.0;\n\nimport { IStatefulERC712 } from \"./interfaces/IStatefulERC712.sol\";\n\nimport { ERC712Extended } from \"./ERC712Extended.sol\";\n\n/**\n * @title  Stateful Extension for EIP-712 typed structured data hashing and signing with nonces.\n * @author M^0 Labs\n * @dev    An abstract implementation to satisfy stateful EIP-712 with nonces.\n */\nabstract contract StatefulERC712 is IStatefulERC712, ERC712Extended {\n    /// @inheritdoc IStatefulERC712\n    mapping(address account => uint256 nonce) public nonces; // Nonces for all signatures.\n\n    /**\n     * @notice Construct the StatefulERC712 contract.\n     * @param  name_ The name of the contract.\n     */\n    constructor(string memory name_) ERC712Extended(name_) {}\n}\n"},{"file_path":"lib/evm-m-extensions/src/components/pausable/Pausable.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.26;\n\nimport { AccessControlUpgradeable } from \"../../../lib/common/lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol\";\nimport { PausableUpgradeable } from \"../../../lib/common/lib/openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol\";\n\nimport { IPausable } from \"./IPausable.sol\";\n\n/**\n * @title Pausable\n * @notice Upgradeable contract that allows to pause the inheriting contract.\n * @dev Relies on PausableUpgradeable from OpenZeppelin for pause functionality.\n * @author M0 Labs\n */\nabstract contract Pausable is IPausable, AccessControlUpgradeable, PausableUpgradeable {\n    /* ============ Variables ============ */\n\n    /// @inheritdoc IPausable\n    bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n    /* ============ Initializer ============ */\n\n    /**\n     * @notice Initializes the contract with the given pauser.\n     * @param pauser The address of a pauser.\n     */\n    function __Pausable_init(address pauser) internal onlyInitializing {\n        if (pauser == address(0)) revert ZeroPauser();\n        _grantRole(PAUSER_ROLE, pauser);\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IPausable\n    function pause() external onlyRole(PAUSER_ROLE) {\n        _beforePause();\n        _pause();\n    }\n\n    /// @inheritdoc IPausable\n    function unpause() external onlyRole(PAUSER_ROLE) {\n        _beforeUnpause();\n        _unpause();\n    }\n\n    /* ============ Hooks For Internal Interactive Functions ============ */\n\n    /**\n     * @dev   Hook called before pausing the contract.\n     */\n    function _beforePause() internal virtual {}\n\n    /**\n     * @dev    Hook called before unpausing the contract.\n     */\n    function _beforeUnpause() internal virtual {}\n}\n"},{"file_path":"lib/evm-m-extensions/lib/common/lib/openzeppelin-contracts-upgradeable/contracts/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":"src/interfaces/IWrappedMToken.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.26;\n\nimport { IERC20Extended } from \"../../lib/common/src/interfaces/IERC20Extended.sol\";\nimport { IMigratable } from \"../../lib/common/src/interfaces/IMigratable.sol\";\n\n/**\n * @title  Wrapped M Token interface extending Extended ERC20.\n * @author M0 Labs\n */\ninterface IWrappedMToken is IMigratable, IERC20Extended {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when some yield is claim for `account` to `recipient`.\n     * @param  account   The account under which yield was generated.\n     * @param  recipient The account that received the yield.\n     * @param  yield     The amount of yield claimed.\n     */\n    event Claimed(address indexed account, address indexed recipient, uint240 yield);\n\n    /**\n     * @notice Emitted when `account` set their yield claim recipient.\n     * @param  account        The account that set their yield claim recipient.\n     * @param  claimRecipient The account that will receive the yield.\n     */\n    event ClaimRecipientSet(address indexed account, address indexed claimRecipient);\n\n    /**\n     * @notice Emitted when Wrapped M earning is enabled.\n     * @param  index The M index at the moment earning is enabled.\n     */\n    event EarningEnabled(uint128 index);\n\n    /**\n     * @notice Emitted when Wrapped M earning is disabled.\n     * @param  index The WrappedM index at the moment earning is disabled.\n     */\n    event EarningDisabled(uint128 index);\n\n    /**\n     * @notice Emitted when this contract's excess M is claimed.\n     * @param  excess The amount of excess M claimed.\n     */\n    event ExcessClaimed(uint240 excess);\n\n    /**\n     * @notice Emitted when the excess destination is set.\n     * @param  excessDestination The address of the new excess destination.\n     */\n    event ExcessDestinationSet(address indexed excessDestination);\n\n    /**\n     * @notice Emitted when `account` starts being an wM earner.\n     * @param  account The account that started earning.\n     */\n    event StartedEarning(address indexed account);\n\n    /**\n     * @notice Emitted when `account` stops being an wM earner.\n     * @param  account The account that stopped earning.\n     */\n    event StoppedEarning(address indexed account);\n\n    /* ============ Custom Errors ============ */\n\n    /// @notice Emitted when performing an operation that is not allowed when earning is disabled.\n    error EarningIsDisabled();\n\n    /// @notice Emitted when performing an operation that is not allowed when earning is enabled.\n    error EarningIsEnabled();\n\n    /**\n     * @notice Emitted when calling `stopEarning` for an account approved as an earner.\n     * @param  account The account that is an approved earner.\n     */\n    error IsApprovedEarner(address account);\n\n    /**\n     * @notice Emitted when there is insufficient balance to decrement from `account`.\n     * @param  account The account with insufficient balance.\n     * @param  balance The balance of the account.\n     * @param  amount  The amount to decrement.\n     */\n    error InsufficientBalance(address account, uint240 balance, uint240 amount);\n\n    /**\n     * @notice Emitted when calling `startEarning` for an account not approved as an earner.\n     * @param  account The account that is not an approved earner.\n     */\n    error NotApprovedEarner(address account);\n\n    /// @notice Emitted when the non-governance migrate function is called by an account other than the migration admin.\n    error UnauthorizedMigration();\n\n    /// @notice Emitted in constructor if default admin is 0x0.\n    error ZeroAdmin();\n\n    /// @notice Emitted in `initialize` if Excess Manager is 0x0.\n    error ZeroExcessManager();\n\n    /// @notice Emitted in `initialize` and `setExcessDestination` if Excess Destination is 0x0.\n    error ZeroExcessDestination();\n\n    /// @notice Emitted in constructor if M Token is 0x0.\n    error ZeroMToken();\n\n    /// @notice Emitted in constructor if Migration Admin is 0x0.\n    error ZeroMigrationAdmin();\n\n    /// @notice Emitted in constructor if Registrar is 0x0.\n    error ZeroRegistrar();\n\n    /// @notice Emitted in constructor if SwapFacility is 0x0.\n    error ZeroSwapFacility();\n\n    /// @notice Emitted in `wrap` and `unwrap` functions if the caller is not the SwapFacility.\n    error NotSwapFacility();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Wraps `amount` M from the caller into wM for `recipient`.\n     * @dev    Can only be called by the SwapFacility.\n     * @param  recipient The account receiving the minted wM.\n     * @param  amount    The amount of wM minted.\n     */\n    function wrap(address recipient, uint256 amount) external;\n\n    /**\n     * @notice Unwraps `amount` wM from the caller into M, sending the M to the SwapFacility.\n     * @dev    Can only be called by the SwapFacility.\n     * @param  recipient Unused. The M is always sent to the SwapFacility, which routes it to the final recipient.\n     * @param  amount    The amount of wM burned.\n     */\n    function unwrap(address recipient, uint256 amount) external;\n\n    /**\n     * @notice Claims any claimable yield for `account`.\n     * @param  account The account under which yield was generated.\n     * @return yield   The amount of yield claimed.\n     */\n    function claimFor(address account) external returns (uint240 yield);\n\n    /**\n     * @notice Claims any excess M of this contract.\n     * @return claimed The amount of excess claimed.\n     */\n    function claimExcess() external returns (uint240 claimed);\n\n    /// @notice Enables earning of Wrapped M if allowed by the Registrar and not already enabled.\n    function enableEarning() external;\n\n    /// @notice Disables earning of Wrapped M if disallowed by the Registrar and not already disabled.\n    function disableEarning() external;\n\n    /**\n     * @notice Starts earning for `account` if allowed by the Registrar.\n     * @param  account The account to start earning for.\n     */\n    function startEarningFor(address account) external;\n\n    /**\n     * @notice Starts earning for multiple accounts if individually allowed by the Registrar.\n     * @param  accounts The accounts to start earning for.\n     */\n    function startEarningFor(address[] calldata accounts) external;\n\n    /**\n     * @notice Stops earning for `account` if disallowed by the Registrar.\n     * @param  account The account to stop earning for.\n     */\n    function stopEarningFor(address account) external;\n\n    /**\n     * @notice Stops earning for multiple accounts if individually disallowed by the Registrar.\n     * @param  accounts The accounts to stop earning for.\n     */\n    function stopEarningFor(address[] calldata accounts) external;\n\n    /**\n     * @notice Explicitly sets the recipient of any yield claimed for the caller.\n     * @param  claimRecipient The account that will receive the caller's yield.\n     */\n    function setClaimRecipient(address claimRecipient) external;\n\n    /**\n     * @notice Sets the destination where excess M is claimed to.\n     * @dev    Can only be called by an account with the `EXCESS_MANAGER_ROLE`.\n     * @param  excessDestination The address of the new excess destination.\n     */\n    function setExcessDestination(address excessDestination) external;\n\n    /* ============ Temporary Admin Migration ============ */\n\n    /**\n     * @notice Performs an arbitrarily defined migration.\n     * @param  migrator The address of a migrator contract.\n     */\n    function migrate(address migrator) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice The role that can set the excess destination.\n    function EXCESS_MANAGER_ROLE() external pure returns (bytes32 excessManagerRole);\n\n    /// @notice Registrar key holding value of whether the earners list can be ignored or not.\n    function EARNERS_LIST_IGNORED_KEY() external pure returns (bytes32 earnersListIgnoredKey);\n\n    /// @notice Registrar key of earners list.\n    function EARNERS_LIST_NAME() external pure returns (bytes32 earnersListName);\n\n    /// @notice Registrar key prefix to determine the override recipient of an account's accrued yield.\n    function CLAIM_OVERRIDE_RECIPIENT_KEY_PREFIX() external pure returns (bytes32 claimOverrideRecipientKeyPrefix);\n\n    /// @notice Registrar key prefix to determine the migrator contract.\n    function MIGRATOR_KEY_PREFIX() external pure returns (bytes32 migratorKeyPrefix);\n\n    /**\n     * @notice Returns the yield accrued for `account`, which is claimable.\n     * @param  account The account being queried.\n     * @return yield   The amount of yield that is claimable.\n     */\n    function accruedYieldOf(address account) external view returns (uint240 yield);\n\n    /**\n     * @notice Returns the token balance of `account` including any accrued yield.\n     * @param  account The address of some account.\n     * @return balance The token balance of `account` including any accrued yield.\n     */\n    function balanceWithYieldOf(address account) external view returns (uint256 balance);\n\n    /**\n     * @notice Returns the earning principal of `account`.\n     * @param  account          The address of some account.\n     * @return earningPrincipal The earning principal of `account`.\n     */\n    function earningPrincipalOf(address account) external view returns (uint112 earningPrincipal);\n\n    /**\n     * @notice Returns the recipient to override as the destination for an account's claim of yield.\n     * @param  account   The account being queried.\n     * @return recipient The address of the recipient, if any, to override as the destination of claimed yield.\n     */\n    function claimRecipientFor(address account) external view returns (address recipient);\n\n    /// @notice The current index of Wrapped M's earning mechanism.\n    function currentIndex() external view returns (uint128 index);\n\n    /// @notice The M token's index when earning was most recently enabled.\n    function enableMIndex() external view returns (uint128 enableMIndex);\n\n    /// @notice This contract's current excess M that is not earmarked for account balances or accrued yield.\n    function excess() external view returns (int256 excess);\n\n    /// @notice The wrapper's index when earning was most recently disabled.\n    function disableIndex() external view returns (uint128 disableIndex);\n\n    /**\n     * @notice Returns whether `account` is a wM earner.\n     * @param  account   The account being queried.\n     * @return isEarning Whether the account is a wM earner.\n     */\n    function isEarning(address account) external view returns (bool isEarning);\n\n    /// @notice Whether Wrapped M earning is enabled.\n    function isEarningEnabled() external view returns (bool isEnabled);\n\n    /// @notice The account that can bypass the Registrar and call the `migrate(address migrator)` function.\n    function migrationAdmin() external view returns (address migrationAdmin);\n\n    /// @notice The address of the M Token contract.\n    function mToken() external view returns (address mToken);\n\n    /// @notice The projected total earning supply if all accrued yield was claimed at this moment.\n    function projectedEarningSupply() external view returns (uint240 supply);\n\n    /// @notice The address of the Registrar.\n    function registrar() external view returns (address registrar);\n\n    /// @notice The portion of total supply that is not earning yield.\n    function totalNonEarningSupply() external view returns (uint240 totalSupply);\n\n    /// @notice The accrued yield of the portion of total supply that is earning yield.\n    function totalAccruedYield() external view returns (uint240 yield);\n\n    /// @notice The portion of total supply that is earning yield.\n    function totalEarningSupply() external view returns (uint240 totalSupply);\n\n    /// @notice The total earning principal to help compute totalAccruedYield(), and thus excess().\n    function totalEarningPrincipal() external view returns (uint112 totalEarningPrincipal);\n\n    /// @notice The address of the destination where excess is claimed to.\n    function excessDestination() external view returns (address excessDestination);\n\n    /// @notice The address of the Swap Facility contract\n    function swapFacility() external view returns (address swapFacility);\n}\n"},{"file_path":"lib/common/lib/openzeppelin-contracts/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev The `account` is missing a role.\n     */\n    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n    /**\n     * @dev The caller of a function is not the expected one.\n     *\n     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n     */\n    error AccessControlBadConfirmation();\n\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 to signal this.\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. This account bears the admin role (for the granted role).\n     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\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 `callerConfirmation`.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n"},{"file_path":"lib/evm-m-extensions/src/components/freezable/IFreezable.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.26;\n\n/**\n * @title Freezable interface.\n * @author M0 Labs\n */\ninterface IFreezable {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when an account is frozen.\n     * @param account The address of the frozen account.\n     * @param timestamp The timestamp at which the account was frozen.\n     */\n    event Frozen(address indexed account, uint256 timestamp);\n\n    /**\n     * @notice Emitted when an account is unfrozen.\n     * @param account The address of the unfrozen account.\n     * @param timestamp The timestamp at which the account was unfrozen.\n     */\n    event Unfrozen(address indexed account, uint256 timestamp);\n\n    /* ============ Errors ============ */\n\n    /**\n     * @notice Emitted when an account is already frozen.\n     * @param account The address of the frozen account.\n     */\n    error AccountFrozen(address account);\n\n    /**\n     * @notice Emitted when an account is not frozen.\n     * @param account The address of the account that is not frozen.\n     */\n    error AccountNotFrozen(address account);\n\n    /// @notice Emitted if no freeze manager is set.\n    error ZeroFreezeManager();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Freezes an account.\n     * @dev MUST only be callable by the FREEZE_MANAGER_ROLE.\n     * @param account The address of the account to freeze.\n     */\n    function freeze(address account) external;\n\n    /**\n     * @notice Freezes multiple accounts.\n     * @dev MUST only be callable by the FREEZE_MANAGER_ROLE.\n     * @param accounts The list of addresses to freeze.\n     */\n    function freezeAccounts(address[] calldata accounts) external;\n\n    /**\n     * @notice Unfreezes an account.\n     * @dev MUST only be callable by the FREEZE_MANAGER_ROLE.\n     * @param account The address of the account to unfreeze.\n     */\n    function unfreeze(address account) external;\n\n    /**\n     * @notice Unfreezes multiple accounts.\n     * @dev MUST only be callable by the FREEZE_MANAGER_ROLE.\n     * @param accounts The list of addresses to unfreeze.\n     */\n    function unfreezeAccounts(address[] calldata accounts) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice The role that can manage the freezelist.\n    function FREEZE_MANAGER_ROLE() external view returns (bytes32);\n\n    /**\n     * @notice Returns whether an account is frozen or not.\n     * @param account The address of the account to check.\n     * @return True if the account is frozen, false otherwise.\n     */\n    function isFrozen(address account) external view returns (bool);\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"mToken_","type":"address"},{"internalType":"address","name":"registrar_","type":"address"},{"internalType":"address","name":"swapFacility_","type":"address"},{"internalType":"address","name":"migrationAdmin_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AccountFrozen","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AccountNotFrozen","type":"error"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"authorizer","type":"address"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"AuthorizationAlreadyUsed","type":"error"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"validBefore","type":"uint256"}],"name":"AuthorizationExpired","type":"error"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"}],"name":"AuthorizationNotYetValid","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"payee","type":"address"}],"name":"CallerMustBePayee","type":"error"},{"inputs":[],"name":"DivisionByZero","type":"error"},{"inputs":[],"name":"EarningIsDisabled","type":"error"},{"inputs":[],"name":"EarningIsEnabled","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InsufficientAmount","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint240","name":"balance","type":"uint240"},{"internalType":"uint240","name":"amount","type":"uint240"}],"name":"InsufficientBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expectedNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidMigrator","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSignatureLength","type":"error"},{"inputs":[],"name":"InvalidSignatureS","type":"error"},{"inputs":[],"name":"InvalidSignatureV","type":"error"},{"inputs":[],"name":"InvalidUInt112","type":"error"},{"inputs":[],"name":"InvalidUInt128","type":"error"},{"inputs":[],"name":"InvalidUInt240","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"IsApprovedEarner","type":"error"},{"inputs":[],"name":"MigrationFailed","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotApprovedEarner","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NotSwapFacility","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"SignerMismatch","type":"error"},{"inputs":[],"name":"UnauthorizedMigration","type":"error"},{"inputs":[],"name":"ZeroAdmin","type":"error"},{"inputs":[],"name":"ZeroExcessDestination","type":"error"},{"inputs":[],"name":"ZeroExcessManager","type":"error"},{"inputs":[],"name":"ZeroForcedTransferManager","type":"error"},{"inputs":[],"name":"ZeroFreezeManager","type":"error"},{"inputs":[],"name":"ZeroMToken","type":"error"},{"inputs":[],"name":"ZeroMigrationAdmin","type":"error"},{"inputs":[],"name":"ZeroMigrator","type":"error"},{"inputs":[],"name":"ZeroPauser","type":"error"},{"inputs":[],"name":"ZeroRegistrar","type":"error"},{"inputs":[],"name":"ZeroSwapFacility","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authorizer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"AuthorizationCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authorizer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"AuthorizationUsed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"claimRecipient","type":"address"}],"name":"ClaimRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint240","name":"yield","type":"uint240"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"index","type":"uint128"}],"name":"EarningDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"index","type":"uint128"}],"name":"EarningEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint240","name":"excess","type":"uint240"}],"name":"ExcessClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"excessDestination","type":"address"}],"name":"ExcessDestinationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"frozenAccount","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"forcedTransferManager","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ForcedTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Frozen","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":"migrator","type":"address"},{"indexed":true,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"Migrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"StartedEarning","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"StoppedEarning","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Unfrozen","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":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"CANCEL_AUTHORIZATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CLAIM_OVERRIDE_RECIPIENT_KEY_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EARNERS_LIST_IGNORED_KEY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EARNERS_LIST_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXCESS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FORCED_TRANSFER_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FREEZE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIGRATOR_KEY_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECEIVE_WITH_AUTHORIZATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSFER_WITH_AUTHORIZATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"accruedYieldOf","outputs":[{"internalType":"uint240","name":"yield_","type":"uint240"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"allowance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"success_","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"authorizer","type":"address"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"authorizationState","outputs":[{"internalType":"bool","name":"isNonceUsed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"balanceWithYieldOf","outputs":[{"internalType":"uint256","name":"balance_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"authorizer_","type":"address"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"vs_","type":"bytes32"}],"name":"cancelAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"authorizer_","type":"address"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"cancelAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"authorizer_","type":"address"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"cancelAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimExcess","outputs":[{"internalType":"uint240","name":"claimed_","type":"uint240"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"claimFor","outputs":[{"internalType":"uint240","name":"yield_","type":"uint240"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"claimRecipientFor","outputs":[{"internalType":"address","name":"recipient_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIndex","outputs":[{"internalType":"uint128","name":"index_","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableEarning","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableIndex","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"earningPrincipalOf","outputs":[{"internalType":"uint112","name":"earningPrincipal_","type":"uint112"}],"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":[],"name":"enableEarning","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableMIndex","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"excess","outputs":[{"internalType":"int256","name":"excess_","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"excessDestination","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"frozenAccount","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"forceTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"frozenAccounts","type":"address[]"},{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"forceTransfers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"freeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"freezeAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin_","type":"address"},{"internalType":"address","name":"freezeManager_","type":"address"},{"internalType":"address","name":"pauser_","type":"address"},{"internalType":"address","name":"forcedTransferManager_","type":"address"},{"internalType":"address","name":"excessManager_","type":"address"},{"internalType":"address","name":"excessDestination_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"isEarning","outputs":[{"internalType":"bool","name":"isEarning_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isEarningEnabled","outputs":[{"internalType":"bool","name":"isEnabled_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"migrator_","type":"address"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrationAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"projectedEarningSupply","outputs":[{"internalType":"uint240","name":"supply_","type":"uint240"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"validAfter_","type":"uint256"},{"internalType":"uint256","name":"validBefore_","type":"uint256"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"receiveWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"validAfter_","type":"uint256"},{"internalType":"uint256","name":"validBefore_","type":"uint256"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"vs_","type":"bytes32"}],"name":"receiveWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"validAfter_","type":"uint256"},{"internalType":"uint256","name":"validBefore_","type":"uint256"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"receiveWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"registrar","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"claimRecipient_","type":"address"}],"name":"setClaimRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"excessDestination_","type":"address"}],"name":"setExcessDestination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"startEarningFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts_","type":"address[]"}],"name":"startEarningFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"stopEarningFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts_","type":"address[]"}],"name":"stopEarningFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapFacility","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAccruedYield","outputs":[{"internalType":"uint240","name":"yield_","type":"uint240"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEarningPrincipal","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEarningSupply","outputs":[{"internalType":"uint240","name":"","type":"uint240"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNonEarningSupply","outputs":[{"internalType":"uint240","name":"","type":"uint240"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"totalSupply_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success_","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender_","type":"address"},{"internalType":"address","name":"recipient_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"success_","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"},{"internalType":"uint256","name":"validAfter_","type":"uint256"},{"internalType":"uint256","name":"validBefore_","type":"uint256"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"vs_","type":"bytes32"}],"name":"transferWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"validAfter_","type":"uint256"},{"internalType":"uint256","name":"validBefore_","type":"uint256"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"transferWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"validAfter_","type":"uint256"},{"internalType":"uint256","name":"validBefore_","type":"uint256"},{"internalType":"bytes32","name":"nonce_","type":"bytes32"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"transferWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unfreeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"unfreezeAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"unwrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"wrap","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"0x000000000000000000000000866a2bf4e572cbcf37d5071a7a58503bfb36be1b000000000000000000000000119fbeedd4f4f4298fb59b720d5654442b81ae2c000000000000000000000000b6807116b3b1b321a390594e31ecd6e0076f6278000000000000000000000000f7298f047f92d0eb21231478ef6ba9fe1ecd4c73"}