creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "lib/protocol/src/MToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { ERC20Extended } from \"../lib/common/src/ERC20Extended.sol\";\nimport { UIntMath } from \"../lib/common/src/libs/UIntMath.sol\";\n\nimport { IERC20 } from \"../lib/common/src/interfaces/IERC20.sol\";\n\nimport { TTGRegistrarReader } from \"./libs/TTGRegistrarReader.sol\";\n\nimport { IContinuousIndexing } from \"./interfaces/IContinuousIndexing.sol\";\nimport { IMToken } from \"./interfaces/IMToken.sol\";\nimport { IRateModel } from \"./interfaces/IRateModel.sol\";\n\nimport { ContinuousIndexing } from \"./abstract/ContinuousIndexing.sol\";\nimport { ContinuousIndexingMath } from \"./libs/ContinuousIndexingMath.sol\";\n\n/*\n\n███╗   ███╗    ████████╗ ██████╗ ██╗  ██╗███████╗███╗   ██╗\n████╗ ████║    ╚══██╔══╝██╔═══██╗██║ ██╔╝██╔════╝████╗  ██║\n██╔████╔██║       ██║   ██║   ██║█████╔╝ █████╗  ██╔██╗ ██║\n██║╚██╔╝██║       ██║   ██║   ██║██╔═██╗ ██╔══╝  ██║╚██╗██║\n██║ ╚═╝ ██║       ██║   ╚██████╔╝██║  ██╗███████╗██║ ╚████║\n╚═╝     ╚═╝       ╚═╝    ╚═════╝ ╚═╝  ╚═╝╚══════╝╚═╝  ╚═══╝\n\n-->> M is for Money. <<--\n\n*/\n\n/**\n * @title  MToken\n * @author M^0 Labs\n * @notice ERC20 M Token.\n */\ncontract MToken is IMToken, ContinuousIndexing, ERC20Extended {\n    /* ============ Structs ============ */\n\n    /**\n     * @notice MToken balance struct.\n     * @param  isEarning  True if the account is earning, false otherwise.\n     * @param  rawBalance Balance (for a non earning account) or balance principal (for an earning account).\n     */\n    struct MBalance {\n        bool isEarning;\n        uint240 rawBalance;\n    }\n\n    /* ============ Variables ============ */\n\n    /// @inheritdoc IMToken\n    address public immutable minterGateway;\n\n    /// @inheritdoc IMToken\n    address public immutable ttgRegistrar;\n\n    /// @inheritdoc IMToken\n    uint240 public totalNonEarningSupply;\n\n    /// @inheritdoc IMToken\n    uint112 public principalOfTotalEarningSupply;\n\n    /// @notice The balance of M for non-earner or principal of earning M balance for earners.\n    mapping(address account => MBalance balance) internal _balances;\n\n    /* ============ Modifiers ============ */\n\n    /// @dev Modifier to check if caller is Minter Gateway.\n    modifier onlyMinterGateway() {\n        if (msg.sender != minterGateway) revert NotMinterGateway();\n\n        _;\n    }\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Constructs the M Token contract.\n     * @param  ttgRegistrar_ The address of the TTG Registrar contract.\n     * @param  minterGateway_     The address of Minter Gateway.\n     */\n    constructor(address ttgRegistrar_, address minterGateway_) ContinuousIndexing() ERC20Extended(\"M by M^0\", \"M\", 6) {\n        if ((ttgRegistrar = ttgRegistrar_) == address(0)) revert ZeroTTGRegistrar();\n        if ((minterGateway = minterGateway_) == address(0)) revert ZeroMinterGateway();\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IMToken\n    function mint(address account_, uint256 amount_) external onlyMinterGateway {\n        _mint(account_, amount_);\n    }\n\n    /// @inheritdoc IMToken\n    function burn(address account_, uint256 amount_) external onlyMinterGateway {\n        _burn(account_, amount_);\n    }\n\n    /// @inheritdoc IMToken\n    function startEarning() external {\n        if (!_isApprovedEarner(msg.sender)) revert NotApprovedEarner();\n\n        _startEarning(msg.sender);\n    }\n\n    /// @inheritdoc IMToken\n    function stopEarning() external {\n        _stopEarning(msg.sender);\n    }\n\n    /// @inheritdoc IMToken\n    function stopEarning(address account_) external {\n        if (_isApprovedEarner(account_)) revert IsApprovedEarner();\n\n        _stopEarning(account_);\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IMToken\n    function rateModel() public view returns (address rateModel_) {\n        return TTGRegistrarReader.getEarnerRateModel(ttgRegistrar);\n    }\n\n    /// @inheritdoc IMToken\n    function earnerRate() public view returns (uint32 earnerRate_) {\n        return _latestRate;\n    }\n\n    /// @inheritdoc IMToken\n    function totalEarningSupply() public view returns (uint240 totalEarningSupply_) {\n        return _getPresentAmount(principalOfTotalEarningSupply);\n    }\n\n    /// @inheritdoc IERC20\n    function totalSupply() external view returns (uint256 totalSupply_) {\n        unchecked {\n            return totalNonEarningSupply + totalEarningSupply();\n        }\n    }\n\n    /// @inheritdoc IMToken\n    function principalBalanceOf(address account_) external view returns (uint240 balance_) {\n        MBalance storage mBalance_ = _balances[account_];\n\n        // Treat the raw balance as principal for earner.\n        return mBalance_.isEarning ? uint112(mBalance_.rawBalance) : 0;\n    }\n\n    /// @inheritdoc IERC20\n    function balanceOf(address account_) external view returns (uint256 balance_) {\n        MBalance storage mBalance_ = _balances[account_];\n\n        return\n            mBalance_.isEarning\n                ? _getPresentAmount(uint112(mBalance_.rawBalance)) // Treat the raw balance as principal for earner.\n                : mBalance_.rawBalance;\n    }\n\n    /// @inheritdoc IMToken\n    function isEarning(address account_) external view returns (bool isEarning_) {\n        return _balances[account_].isEarning;\n    }\n\n    /// @inheritdoc IContinuousIndexing\n    function currentIndex() public view override(ContinuousIndexing, IContinuousIndexing) returns (uint128) {\n        // NOTE: Safe to use unchecked here, since `block.timestamp` is always greater than `latestUpdateTimestamp`.\n        unchecked {\n            return\n                // NOTE: Cap the index to `type(uint128).max` to prevent overflow in present value math.\n                UIntMath.bound128(\n                    ContinuousIndexingMath.multiplyIndicesDown(\n                        latestIndex,\n                        ContinuousIndexingMath.getContinuousIndex(\n                            ContinuousIndexingMath.convertFromBasisPoints(_latestRate),\n                            uint32(block.timestamp - latestUpdateTimestamp)\n                        )\n                    )\n                );\n        }\n    }\n\n    /* ============ Internal Interactive Functions ============ */\n\n    /**\n     * @dev   Adds principal to `_balances` of an earning account.\n     * @param account_         The account to add principal to.\n     * @param principalAmount_ The principal amount to add.\n     */\n    function _addEarningAmount(address account_, uint112 principalAmount_) internal {\n        // NOTE: Safe to use unchecked here since overflow of the total supply is checked in `_mint`.\n        unchecked {\n            _balances[account_].rawBalance += principalAmount_;\n            principalOfTotalEarningSupply += principalAmount_;\n        }\n    }\n\n    /**\n     * @dev   Adds amount to `_balances` of a non-earning account.\n     * @param account_ The account to add amount to.\n     * @param amount_  The amount to add.\n     */\n    function _addNonEarningAmount(address account_, uint240 amount_) internal {\n        // NOTE: Safe to use unchecked here since overflow of the total supply is checked in `_mint`.\n        unchecked {\n            _balances[account_].rawBalance += amount_;\n            totalNonEarningSupply += amount_;\n        }\n    }\n\n    /**\n     * @dev   Burns amount of earning or non-earning M from account.\n     * @param account_ The account to burn from.\n     * @param amount_  The present amount to burn.\n     */\n    function _burn(address account_, uint256 amount_) internal {\n        _revertIfInsufficientAmount(amount_);\n\n        emit Transfer(account_, address(0), amount_);\n\n        if (_balances[account_].isEarning) {\n            // NOTE: When burning a present amount, round the principal up in favor of the protocol.\n            _subtractEarningAmount(account_, _getPrincipalAmountRoundedUp(UIntMath.safe240(amount_)));\n            updateIndex();\n        } else {\n            _subtractNonEarningAmount(account_, UIntMath.safe240(amount_));\n        }\n    }\n\n    /**\n     * @dev   Mints amount of earning or non-earning M to account.\n     * @param recipient_ The account to mint to.\n     * @param amount_    The present amount to mint.\n     */\n    function _mint(address recipient_, uint256 amount_) internal {\n        _revertIfInsufficientAmount(amount_);\n        _revertIfInvalidRecipient(recipient_);\n\n        emit Transfer(address(0), recipient_, amount_);\n\n        uint240 safeAmount_ = UIntMath.safe240(amount_);\n\n        unchecked {\n            // As an edge case precaution, prevent a mint that, if all tokens (earning and non-earning) were converted\n            // to a principal earning amount, would overflow the `uint112 principalOfTotalEarningSupply`.\n            if (\n                uint256(totalNonEarningSupply) + safeAmount_ > type(uint240).max ||\n                // NOTE: Round the principal up for worst case.\n                uint256(principalOfTotalEarningSupply) +\n                    _getPrincipalAmountRoundedUp(totalNonEarningSupply + safeAmount_) >=\n                type(uint112).max\n            ) {\n                revert OverflowsPrincipalOfTotalSupply();\n            }\n        }\n\n        if (_balances[recipient_].isEarning) {\n            // NOTE: When minting a present amount, round the principal down in favor of the protocol.\n            _addEarningAmount(recipient_, _getPrincipalAmountRoundedDown(safeAmount_));\n            updateIndex();\n        } else {\n            _addNonEarningAmount(recipient_, safeAmount_);\n        }\n    }\n\n    /**\n     * @dev   Starts earning for account.\n     * @param account_ The account to start earning for.\n     */\n    function _startEarning(address account_) internal {\n        MBalance storage mBalance_ = _balances[account_];\n\n        if (mBalance_.isEarning) return;\n\n        emit StartedEarning(account_);\n\n        mBalance_.isEarning = true;\n\n        // Treat the raw balance as present amount for non earner.\n        uint240 amount_ = mBalance_.rawBalance;\n\n        if (amount_ == 0) return;\n\n        // NOTE: When converting a non-earning balance into an earning balance,\n        // round the principal down in favor of the protocol.\n        uint112 principalAmount_ = _getPrincipalAmountRoundedDown(amount_);\n\n        _balances[account_].rawBalance = principalAmount_;\n\n        unchecked {\n            principalOfTotalEarningSupply += principalAmount_;\n            totalNonEarningSupply -= amount_;\n        }\n\n        updateIndex();\n    }\n\n    /**\n     * @dev   Stops earning for account.\n     * @param account_ The account to stop earning for.\n     */\n    function _stopEarning(address account_) internal {\n        MBalance storage mBalance_ = _balances[account_];\n\n        if (!mBalance_.isEarning) return;\n\n        emit StoppedEarning(account_);\n\n        mBalance_.isEarning = false;\n\n        // Treat the raw balance as principal for earner.\n        uint112 principalAmount_ = uint112(_balances[account_].rawBalance);\n\n        if (principalAmount_ == 0) return;\n\n        uint240 amount_ = _getPresentAmount(principalAmount_);\n\n        _balances[account_].rawBalance = amount_;\n\n        unchecked {\n            totalNonEarningSupply += amount_;\n            principalOfTotalEarningSupply -= principalAmount_;\n        }\n\n        updateIndex();\n    }\n\n    /**\n     * @dev   Subtracts principal from `_balances` of an earning account.\n     * @param account_         The account to subtract principal from.\n     * @param principalAmount_ The principal amount to subtract.\n     */\n    function _subtractEarningAmount(address account_, uint112 principalAmount_) internal {\n        uint256 rawBalance_ = _balances[account_].rawBalance;\n\n        if (rawBalance_ < principalAmount_) revert InsufficientBalance(account_, rawBalance_, principalAmount_);\n\n        unchecked {\n            // Overflow not possible given the above check.\n            _balances[account_].rawBalance -= principalAmount_;\n            principalOfTotalEarningSupply -= principalAmount_;\n        }\n    }\n\n    /**\n     * @dev   Subtracts amount from `_balances` of a non-earning account.\n     * @param account_ The account to subtract amount from.\n     * @param amount_  The amount to subtract.\n     */\n    function _subtractNonEarningAmount(address account_, uint240 amount_) internal {\n        uint256 rawBalance_ = _balances[account_].rawBalance;\n\n        if (rawBalance_ < amount_) revert InsufficientBalance(account_, rawBalance_, amount_);\n\n        unchecked {\n            // Overflow not possible given the above check.\n            _balances[account_].rawBalance -= amount_;\n            totalNonEarningSupply -= amount_;\n        }\n    }\n\n    /**\n     * @dev   Transfer M between both earning and non-earning accounts.\n     * @param sender_    The account to transfer from. It can be either earning or non-earning account.\n     * @param recipient_ The account to transfer to. It can be either earning or non-earning account.\n     * @param amount_    The present amount to transfer.\n     */\n    function _transfer(address sender_, address recipient_, uint256 amount_) internal override {\n        _revertIfInvalidRecipient(recipient_);\n\n        emit Transfer(sender_, recipient_, amount_);\n\n        uint240 safeAmount_ = UIntMath.safe240(amount_);\n\n        bool senderIsEarning_ = _balances[sender_].isEarning; // Only using the sender's earning status more than once.\n\n        // If this is an in-kind transfer, then...\n        if (senderIsEarning_ == _balances[recipient_].isEarning) {\n            // NOTE: When subtracting a present amount from an earner, round the principal up in favor of the protocol.\n            return\n                _transferAmountInKind( // perform an in-kind transfer with...\n                    sender_,\n                    recipient_,\n                    senderIsEarning_ ? _getPrincipalAmountRoundedUp(safeAmount_) : safeAmount_ // the appropriate amount\n                );\n        }\n\n        // If this is not an in-kind transfer, then...\n        if (senderIsEarning_) {\n            // either the sender is earning and the recipient is not, or...\n            // NOTE: When subtracting a present amount from an earner, round the principal up in favor of the protocol.\n            _subtractEarningAmount(sender_, _getPrincipalAmountRoundedUp(safeAmount_));\n            _addNonEarningAmount(recipient_, safeAmount_);\n        } else {\n            // the sender is not earning and the recipient is.\n            // NOTE: When adding a present amount to an earner, round the principal down in favor of the protocol.\n            _subtractNonEarningAmount(sender_, safeAmount_);\n            _addEarningAmount(recipient_, _getPrincipalAmountRoundedDown(safeAmount_));\n        }\n\n        updateIndex();\n    }\n\n    /**\n     * @dev   Transfer M between same earning status accounts.\n     * @param sender_    The account to transfer from.\n     * @param recipient_ The account to transfer to.\n     * @param amount_    The amount (present or principal) to transfer.\n     */\n    function _transferAmountInKind(address sender_, address recipient_, uint240 amount_) internal {\n        uint256 rawBalance_ = _balances[sender_].rawBalance;\n\n        if (rawBalance_ < amount_) revert InsufficientBalance(sender_, rawBalance_, amount_);\n\n        // NOTE: When transferring an amount in kind, the `rawBalance` can't overflow\n        //       since the total supply would have overflowed first when minting.\n        unchecked {\n            _balances[sender_].rawBalance -= amount_;\n            _balances[recipient_].rawBalance += amount_;\n        }\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Returns the present amount (rounded down) given the principal amount, using the current index.\n     *         All present amounts are rounded down in favor of the protocol.\n     * @param  principalAmount_ The principal amount.\n     * @return The present amount.\n     */\n    function _getPresentAmount(uint112 principalAmount_) internal view returns (uint240) {\n        return _getPresentAmount(principalAmount_, currentIndex());\n    }\n\n    /**\n     * @dev    Returns the present amount (rounded down) given the principal amount and an index.\n     *         All present amounts are rounded down in favor of the protocol, since they are assets.\n     * @param  principalAmount_ The principal amount.\n     * @param  index_           An index\n     * @return The present amount.\n     */\n    function _getPresentAmount(uint112 principalAmount_, uint128 index_) internal pure returns (uint240) {\n        return _getPresentAmountRoundedDown(principalAmount_, index_);\n    }\n\n    /**\n     * @dev    Checks if earner was approved by TTG.\n     * @param  account_    The account to check.\n     * @return True if approved, false otherwise.\n     */\n    function _isApprovedEarner(address account_) internal view returns (bool) {\n        return\n            TTGRegistrarReader.isEarnersListIgnored(ttgRegistrar) ||\n            TTGRegistrarReader.isApprovedEarner(ttgRegistrar, account_);\n    }\n\n    /**\n     * @dev    Gets the current earner rate from TTG approved rate model contract.\n     * @return rate_ The current earner rate.\n     */\n    function _rate() internal view override returns (uint32 rate_) {\n        (bool success_, bytes memory returnData_) = rateModel().staticcall(\n            abi.encodeWithSelector(IRateModel.rate.selector)\n        );\n\n        rate_ = (success_ && returnData_.length >= 32) ? UIntMath.bound32(abi.decode(returnData_, (uint256))) : 0;\n    }\n\n    /**\n     * @dev   Reverts if the amount of a `mint` or `burn` is equal to 0.\n     * @param amount_ Amount to check.\n     */\n    function _revertIfInsufficientAmount(uint256 amount_) internal pure {\n        if (amount_ == 0) revert InsufficientAmount(amount_);\n    }\n\n    /**\n     * @dev   Reverts if the recipient of a `mint` or `transfer` is address(0).\n     * @param recipient_ Address of the recipient to check.\n     */\n    function _revertIfInvalidRecipient(address recipient_) internal pure {\n        if (recipient_ == address(0)) revert InvalidRecipient(recipient_);\n    }\n}\n"
      },
      "lib/protocol/lib/common/src/ERC20Extended.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC20 } from \"./interfaces/IERC20.sol\";\nimport { IERC20Extended } from \"./interfaces/IERC20Extended.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    /// @inheritdoc IERC20\n    string public 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 = 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 returns (string memory name_) {\n        return _name;\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"
      },
      "lib/protocol/lib/common/src/libs/UIntMath.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\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 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 given uint256 value to a uint16,\n     *         ensuring that it is less than or equal to the maximum uint16 value.\n     * @param  n The value to check.\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 given uint256 value to a uint40,\n     *         ensuring that it is less than or equal to the maximum uint40 value.\n     * @param  n The value to check.\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 given uint256 value to a uint48,\n     *         ensuring that it is less than or equal to the maximum uint48 value.\n     * @param  n The value to check.\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 given uint256 value to a uint112,\n     *         ensuring that it is less than or equal to the maximum uint112 value.\n     * @param  n The value to check.\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 given uint256 value to a uint128,\n     *         ensuring that it is less than or equal to the maximum uint128 value.\n     * @param  n The value to check.\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 given uint256 value to a uint240,\n     *         ensuring that it is less than or equal to the maximum uint240 value.\n     * @param  n The value to check.\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 given uint256 value to the maximum uint32 value.\n     * @param  n The value to check.\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 given uint256 value to the maximum uint112 value.\n     * @param  n The value to check.\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 given uint256 value to the maximum uint128 value.\n     * @param  n The value to check.\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 given uint256 value to the maximum uint240 value.\n     * @param  n The value to check.\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 check.\n     * @param  b_  Value to check.\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 check.\n     * @param  b_  Value to check.\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 uint32 values and returns the lesser one.\n     * @param  a_  Value to check.\n     * @param  b_  Value to check.\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 check.\n     * @param  b_  Value to check.\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 check.\n     * @param  b_  Value to check.\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 check.\n     * @param  b_  Value to check.\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 check.\n     * @param  b_  Value to check.\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"
      },
      "lib/protocol/lib/common/src/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  ERC20 Token Standard.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-20: https://eips.ethereum.org/EIPS/eip-20\n */\ninterface IERC20 {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when `spender` has been approved for `amount` of the token balance of `account`.\n     * @param  account The address of the account.\n     * @param  spender The address of the spender being approved for the allowance.\n     * @param  amount  The amount of the allowance being approved.\n     */\n    event Approval(address indexed account, address indexed spender, uint256 amount);\n\n    /**\n     * @notice Emitted when `amount` tokens is transferred from `sender` to `recipient`.\n     * @param  sender    The address of the sender who's token balance is decremented.\n     * @param  recipient The address of the recipient who's token balance is incremented.\n     * @param  amount    The amount of tokens being transferred.\n     */\n    event Transfer(address indexed sender, address indexed recipient, uint256 amount);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Allows a calling account to approve `spender` to spend up to `amount` of its token balance.\n     * @dev    MUST emit an `Approval` event.\n     * @param  spender The address of the account being allowed to spend up to the allowed amount.\n     * @param  amount  The amount of the allowance being approved.\n     * @return Whether or not the approval was successful.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @notice Allows a calling account to transfer `amount` tokens to `recipient`.\n     * @param  recipient The address of the recipient who's token balance will be incremented.\n     * @param  amount    The amount of tokens being transferred.\n     * @return Whether or not the transfer was successful.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @notice Allows a calling account to transfer `amount` tokens from `sender`, with allowance, to a `recipient`.\n     * @param  sender    The address of the sender who's token balance will be decremented.\n     * @param  recipient The address of the recipient who's token balance will be incremented.\n     * @param  amount    The amount of tokens being transferred.\n     * @return Whether or not the transfer was successful.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the allowance `spender` is allowed to spend on behalf of `account`.\n     * @param  account The address of the account who's token balance `spender` is allowed to spend.\n     * @param  spender The address of an account allowed to spend on behalf of `account`.\n     * @return The amount `spender` can spend on behalf of `account`.\n     */\n    function allowance(address account, address spender) external view returns (uint256);\n\n    /**\n     * @notice Returns the token balance of `account`.\n     * @param  account The address of some account.\n     * @return The token balance of `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /// @notice Returns the number of decimals UIs should assume all amounts have.\n    function decimals() external view returns (uint8);\n\n    /// @notice Returns the name of the contract/token.\n    function name() external view returns (string memory);\n\n    /// @notice Returns the symbol of the token.\n    function symbol() external view returns (string memory);\n\n    /// @notice Returns the current total supply of the token.\n    function totalSupply() external view returns (uint256);\n}\n"
      },
      "lib/protocol/src/libs/TTGRegistrarReader.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { ITTGRegistrar } from \"../interfaces/ITTGRegistrar.sol\";\n\n/**\n * @title  Library to read TTG (Two Token Governance) Registrar contract parameters.\n * @author M^0 Labs\n */\nlibrary TTGRegistrarReader {\n    /* ============ Variables ============ */\n\n    /// @notice The name of parameter in TTG that defines the earner rate model contract.\n    bytes32 internal constant EARNER_RATE_MODEL = \"earner_rate_model\";\n\n    /// @notice The parameter name in TTG that defines the earners list.\n    bytes32 internal constant EARNERS_LIST = \"earners\";\n\n    /// @notice The parameter name in TTG that defines whether to ignore the earners list or not.\n    bytes32 internal constant EARNERS_LIST_IGNORED = \"earners_list_ignored\";\n\n    /// @notice The parameter name in TTG that defines the time to wait for mint request to be processed.\n    bytes32 internal constant MINT_DELAY = \"mint_delay\";\n\n    /// @notice The parameter name in TTG that defines the mint ratio.\n    bytes32 internal constant MINT_RATIO = \"mint_ratio\"; // bps\n\n    /// @notice The parameter name in TTG that defines the time while mint request can still be processed.\n    bytes32 internal constant MINT_TTL = \"mint_ttl\";\n\n    /// @notice The parameter name in TTG that defines the time to freeze minter.\n    bytes32 internal constant MINTER_FREEZE_TIME = \"minter_freeze_time\";\n\n    /// @notice The parameter name in TTG that defines the minter rate model contract.\n    bytes32 internal constant MINTER_RATE_MODEL = \"minter_rate_model\";\n\n    /// @notice The parameter name in TTG that defines the minters list.\n    bytes32 internal constant MINTERS_LIST = \"minters\";\n\n    /// @notice The parameter name in TTG that defines the penalty rate.\n    bytes32 internal constant PENALTY_RATE = \"penalty_rate\"; // bps\n\n    /// @notice The parameter name in TTG that defines the required interval to update collateral.\n    bytes32 internal constant UPDATE_COLLATERAL_INTERVAL = \"update_collateral_interval\";\n\n    /// @notice The parameter name that defines number of signatures required for successful collateral update.\n    bytes32 internal constant UPDATE_COLLATERAL_VALIDATOR_THRESHOLD = \"update_collateral_threshold\";\n\n    /// @notice The parameter name in TTG that defines the validators list.\n    bytes32 internal constant VALIDATORS_LIST = \"validators\";\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /// @notice Gets the earner rate model contract address.\n    function getEarnerRateModel(address registrar_) internal view returns (address) {\n        return toAddress(_get(registrar_, EARNER_RATE_MODEL));\n    }\n\n    /// @notice Gets the mint delay.\n    function getMintDelay(address registrar_) internal view returns (uint256) {\n        return uint256(_get(registrar_, MINT_DELAY));\n    }\n\n    /// @notice Gets the minter freeze time.\n    function getMinterFreezeTime(address registrar_) internal view returns (uint256) {\n        return uint256(_get(registrar_, MINTER_FREEZE_TIME));\n    }\n\n    /// @notice Gets the minter rate model contract address.\n    function getMinterRateModel(address registrar_) internal view returns (address) {\n        return toAddress(_get(registrar_, MINTER_RATE_MODEL));\n    }\n\n    /// @notice Gets the mint TTL.\n    function getMintTTL(address registrar_) internal view returns (uint256) {\n        return uint256(_get(registrar_, MINT_TTL));\n    }\n\n    /// @notice Gets the mint ratio.\n    function getMintRatio(address registrar_) internal view returns (uint256) {\n        return uint256(_get(registrar_, MINT_RATIO));\n    }\n\n    /// @notice Gets the update collateral interval.\n    function getUpdateCollateralInterval(address registrar_) internal view returns (uint256) {\n        return uint256(_get(registrar_, UPDATE_COLLATERAL_INTERVAL));\n    }\n\n    /// @notice Gets the update collateral validator threshold.\n    function getUpdateCollateralValidatorThreshold(address registrar_) internal view returns (uint256) {\n        return uint256(_get(registrar_, UPDATE_COLLATERAL_VALIDATOR_THRESHOLD));\n    }\n\n    /// @notice Checks if the given earner is approved.\n    function isApprovedEarner(address registrar_, address earner_) internal view returns (bool) {\n        return _contains(registrar_, EARNERS_LIST, earner_);\n    }\n\n    /// @notice Checks if the `earners_list_ignored` exists.\n    function isEarnersListIgnored(address registrar_) internal view returns (bool) {\n        return _get(registrar_, EARNERS_LIST_IGNORED) != bytes32(0);\n    }\n\n    /// @notice Checks if the given minter is approved.\n    function isApprovedMinter(address registrar_, address minter_) internal view returns (bool) {\n        return _contains(registrar_, MINTERS_LIST, minter_);\n    }\n\n    /// @notice Checks if the given validator is approved.\n    function isApprovedValidator(address registrar_, address validator_) internal view returns (bool) {\n        return _contains(registrar_, VALIDATORS_LIST, validator_);\n    }\n\n    /// @notice Gets the penalty rate.\n    function getPenaltyRate(address registrar_) internal view returns (uint256) {\n        return uint256(_get(registrar_, PENALTY_RATE));\n    }\n\n    /// @notice Gets the vault contract address.\n    function getVault(address registrar_) internal view returns (address) {\n        return ITTGRegistrar(registrar_).vault();\n    }\n\n    /// @notice Converts given bytes32 to address.\n    function toAddress(bytes32 input_) internal pure returns (address) {\n        return address(uint160(uint256(input_)));\n    }\n\n    /// @notice Checks if the given list contains the given account.\n    function _contains(address registrar_, bytes32 listName_, address account_) private view returns (bool) {\n        return ITTGRegistrar(registrar_).listContains(listName_, account_);\n    }\n\n    /// @notice Gets the value of the given key.\n    function _get(address registrar_, bytes32 key_) private view returns (bytes32) {\n        return ITTGRegistrar(registrar_).get(key_);\n    }\n}\n"
      },
      "lib/protocol/src/interfaces/IContinuousIndexing.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  Continuous Indexing Interface.\n * @author M^0 Labs\n */\ninterface IContinuousIndexing {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when the index is updated.\n     * @param  index The new index.\n     * @param  rate  The current rate.\n     */\n    event IndexUpdated(uint128 indexed index, uint32 indexed rate);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Updates the latest index and latest accrual time in storage.\n     * @return index The new stored index for computing present amounts from principal amounts.\n     */\n    function updateIndex() external returns (uint128);\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice The current index that would be written to storage if `updateIndex` is called.\n    function currentIndex() external view returns (uint128);\n\n    /// @notice The latest updated index.\n    function latestIndex() external view returns (uint128);\n\n    /// @notice The latest timestamp when the index was updated.\n    function latestUpdateTimestamp() external view returns (uint40);\n}\n"
      },
      "lib/protocol/src/interfaces/IMToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC20Extended } from \"../../lib/common/src/interfaces/IERC20Extended.sol\";\n\nimport { IContinuousIndexing } from \"./IContinuousIndexing.sol\";\n\n/**\n * @title  M Token Interface.\n * @author M^0 Labs\n */\ninterface IMToken is IContinuousIndexing, IERC20Extended {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when account starts being an M 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 M earner.\n     * @param  account The account that stopped earning.\n     */\n    event StoppedEarning(address indexed account);\n\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Emitted when there is insufficient balance to decrement from `account`.\n     * @param  account     The account with insufficient balance.\n     * @param  rawBalance  The raw balance of the account.\n     * @param  amount      The amount to decrement the `rawBalance` by.\n     */\n    error InsufficientBalance(address account, uint256 rawBalance, uint256 amount);\n\n    /// @notice Emitted when calling `stopEarning` for an account approved as earner by TTG.\n    error IsApprovedEarner();\n\n    /// @notice Emitted when calling `startEarning` for an account not approved as earner by TTG.\n    error NotApprovedEarner();\n\n    /// @notice Emitted when calling `mint`, `burn` not by Minter Gateway.\n    error NotMinterGateway();\n\n    /// @notice Emitted when principal of total supply (earning and non-earning) will overflow a `type(uint112).max`.\n    error OverflowsPrincipalOfTotalSupply();\n\n    /// @notice Emitted in constructor if Minter Gateway is 0x0.\n    error ZeroMinterGateway();\n\n    /// @notice Emitted in constructor if TTG Registrar is 0x0.\n    error ZeroTTGRegistrar();\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Mints tokens.\n     * @param  account The address of account to mint to.\n     * @param  amount  The amount of M Token to mint.\n     */\n    function mint(address account, uint256 amount) external;\n\n    /**\n     * @notice Burns tokens.\n     * @param  account The address of account to burn from.\n     * @param  amount  The amount of M Token to burn.\n     */\n    function burn(address account, uint256 amount) external;\n\n    /// @notice Starts earning for caller if allowed by TTG.\n    function startEarning() external;\n\n    /// @notice Stops earning for caller.\n    function stopEarning() external;\n\n    /**\n     * @notice Stops earning for `account`.\n     * @dev    MUST revert if `account` is an approved earner in TTG Registrar.\n     * @param  account The account to stop earning for.\n     */\n    function stopEarning(address account) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice The address of the Minter Gateway contract.\n    function minterGateway() external view returns (address);\n\n    /// @notice The address of the TTG Registrar contract.\n    function ttgRegistrar() external view returns (address);\n\n    /// @notice The address of TTG approved earner rate model.\n    function rateModel() external view returns (address);\n\n    /// @notice The current value of earner rate in basis points.\n    function earnerRate() external view returns (uint32);\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    /// @notice The principal of the total earning supply of M Token.\n    function principalOfTotalEarningSupply() external view returns (uint112);\n\n    /// @notice The total earning supply of M Token.\n    function totalEarningSupply() external view returns (uint240);\n\n    /// @notice The total non-earning supply of M Token.\n    function totalNonEarningSupply() external view returns (uint240);\n\n    /**\n     * @notice Checks if account is an earner.\n     * @param  account The account to check.\n     * @return True if account is an earner, false otherwise.\n     */\n    function isEarning(address account) external view returns (bool);\n}\n"
      },
      "lib/protocol/src/interfaces/IRateModel.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  Rate Model Interface.\n * @author M^0 Labs\n */\ninterface IRateModel {\n    /**\n     * @notice Returns the current yearly rate in BPS.\n     *         This value does not account for the compounding interest.\n     */\n    function rate() external view returns (uint256);\n}\n"
      },
      "lib/protocol/src/abstract/ContinuousIndexing.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IContinuousIndexing } from \"../interfaces/IContinuousIndexing.sol\";\n\nimport { ContinuousIndexingMath } from \"../libs/ContinuousIndexingMath.sol\";\n\n/**\n * @title Abstract Continuous Indexing Contract to handle rate/index updates in inheriting contracts.\n * @author M^0 Labs\n */\nabstract contract ContinuousIndexing is IContinuousIndexing {\n    /* ============ Variables ============ */\n\n    /// @inheritdoc IContinuousIndexing\n    uint128 public latestIndex;\n\n    /// @dev The latest updated rate.\n    uint32 internal _latestRate;\n\n    /// @inheritdoc IContinuousIndexing\n    uint40 public latestUpdateTimestamp;\n\n    /* ============ Constructor ============ */\n\n    /// @notice Constructs the ContinuousIndexing contract.\n    constructor() {\n        latestIndex = ContinuousIndexingMath.EXP_SCALED_ONE;\n        latestUpdateTimestamp = uint40(block.timestamp);\n    }\n\n    /* ============ Interactive Functions ============ */\n\n    /// @inheritdoc IContinuousIndexing\n    function updateIndex() public virtual returns (uint128 currentIndex_) {\n        // NOTE: `_rate()` can depend indirectly on `latestIndex` and `latestUpdateTimestamp`, if the RateModel\n        //       depends on earning balances/supply, which depends on `currentIndex()`, so only update them after this.\n        uint32 rate_ = _rate();\n\n        if (latestUpdateTimestamp == block.timestamp && _latestRate == rate_) return latestIndex;\n\n        // NOTE: `currentIndex()` depends on `_latestRate`, so only update it after this.\n        latestIndex = currentIndex_ = currentIndex();\n        _latestRate = rate_;\n        latestUpdateTimestamp = uint40(block.timestamp);\n\n        emit IndexUpdated(currentIndex_, rate_);\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IContinuousIndexing\n    function currentIndex() public view virtual returns (uint128);\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Returns the principal amount (rounded down) given the present amount, using the current index.\n     * @param  presentAmount_ The present amount.\n     * @return The principal amount rounded down.\n     */\n    function _getPrincipalAmountRoundedDown(uint240 presentAmount_) internal view returns (uint112) {\n        return _getPrincipalAmountRoundedDown(presentAmount_, currentIndex());\n    }\n\n    /**\n     * @dev    Returns the principal amount (rounded up) given the present amount and an index.\n     * @param  presentAmount_ The present amount.\n     * @return The principal amount rounded up.\n     */\n    function _getPrincipalAmountRoundedUp(uint240 presentAmount_) internal view returns (uint112) {\n        return _getPrincipalAmountRoundedUp(presentAmount_, currentIndex());\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 ContinuousIndexingMath.multiplyDown(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 ContinuousIndexingMath.multiplyUp(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 ContinuousIndexingMath.divideDown(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 ContinuousIndexingMath.divideUp(presentAmount_, index_);\n    }\n\n    /// @dev To be overridden by the inheriting contract to return the current rate.\n    function _rate() internal view virtual returns (uint32);\n}\n"
      },
      "lib/protocol/src/libs/ContinuousIndexingMath.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { UIntMath } from \"../../lib/common/src/libs/UIntMath.sol\";\n\n/**\n * @title  Arithmetic library with operations for calculating continuous indexing.\n * @author M^0 Labs\n */\nlibrary ContinuousIndexingMath {\n    /* ============ Variables ============ */\n\n    /// @notice The number of seconds in a year.\n    uint32 internal constant SECONDS_PER_YEAR = 31_536_000;\n\n    /// @notice 100% in basis points.\n    uint16 internal constant BPS_SCALED_ONE = 1e4;\n\n    /// @notice The scaling of rates in 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    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @notice Helper function to calculate `(x * EXP_SCALED_ONE) / index`, rounded down.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function divideDown(uint240 x, uint128 index) internal pure returns (uint112 z) {\n        if (index == 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            //       `multiplyDown` or `multiplyUp`, which would already satisfy\n            //       `uint256(x) * EXP_SCALED_ONE < type(uint240).max`.\n            return UIntMath.safe112((uint256(x) * EXP_SCALED_ONE) / index);\n        }\n    }\n\n    /**\n     * @notice Helper function to calculate `(x * EXP_SCALED_ONE) / index`, rounded up.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function divideUp(uint240 x, uint128 index) internal pure returns (uint112 z) {\n        if (index == 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            //       `multiplyDown` or `multiplyUp`, which would already satisfy\n            //       `uint256(x) * EXP_SCALED_ONE < type(uint240).max`.\n            return UIntMath.safe112(((uint256(x) * EXP_SCALED_ONE) + index - 1) / index);\n        }\n    }\n\n    /**\n     * @notice Helper function to calculate `(x * index) / EXP_SCALED_ONE`, rounded down.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function multiplyDown(uint112 x, uint128 index) internal pure returns (uint240 z) {\n        unchecked {\n            return uint240((uint256(x) * index) / 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 multiplyUp(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     * @notice Helper function to calculate `(index * deltaIndex) / EXP_SCALED_ONE`, rounded down.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function multiplyIndicesDown(uint128 index, uint48 deltaIndex) internal pure returns (uint144 z) {\n        unchecked {\n            return uint144((uint256(index) * deltaIndex) / EXP_SCALED_ONE);\n        }\n    }\n\n    /**\n     * @notice Helper function to calculate `(index * deltaIndex) / EXP_SCALED_ONE`, rounded up.\n     * @dev    Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\n     */\n    function multiplyIndicesUp(uint128 index, uint48 deltaIndex) internal pure returns (uint144 z) {\n        unchecked {\n            return uint144((uint256(index) * deltaIndex + (EXP_SCALED_ONE - 1)) / EXP_SCALED_ONE);\n        }\n    }\n\n    /**\n     * @notice Helper function to calculate e^rt (continuous compounding formula).\n     * @dev    `uint64 yearlyRate` can accommodate 1000% interest per year.\n     * @dev    `uint32 time` can accommodate 100 years.\n     * @dev    `type(uint64).max * type(uint32).max / SECONDS_PER_YEAR` fits in a `uint72`.\n     */\n    function getContinuousIndex(uint64 yearlyRate, uint32 time) internal pure returns (uint48 index) {\n        unchecked {\n            // NOTE: Casting `uint256(yearlyRate) * time` to a `uint72` is safe because the largest value is\n            //      `type(uint64).max * type(uint32).max / SECONDS_PER_YEAR`, which is less than `type(uint72).max`.\n            return exponent(uint72((uint256(yearlyRate) * time) / SECONDS_PER_YEAR));\n        }\n    }\n\n    /**\n     * @notice Helper function to calculate y = e^x using R(4,4) Padé approximation:\n     *           e(x) = (1 + x/2 + 3(x^2)/28 + x^3/84 + x^4/1680) / (1 - x/2 + 3(x^2)/28 - x^3/84 + x^4/1680)\n     *           See: https://en.wikipedia.org/wiki/Pad%C3%A9_table\n     *           See: https://www.wolframalpha.com/input?i=PadeApproximant%5Bexp%5Bx%5D%2C%7Bx%2C0%2C%7B4%2C+4%7D%7D%5D\n     *         Despite itself being a whole number, `x` represents a real number scaled by `EXP_SCALED_ONE`, thus\n     *         allowing for y = e^x where x is a real number.\n     * @dev    Output `y` for a `uint72` input `x` will fit in `uint48`\n     */\n    function exponent(uint72 x) internal pure returns (uint48 y) {\n        // NOTE: This can be done unchecked even for `x = type(uint72).max`.\n        //       Verify by removing `unchecked` and running `test_exponent()`.\n        unchecked {\n            uint256 x2 = uint256(x) * x;\n\n            // `additiveTerms` is `(1 + 3(x^2)/28 + x^4/1680)`, and scaled by `84e27`.\n            // NOTE: `84e27` the cleanest and largest scalar, given the various intermediate overflow possibilities.\n            // NOTE: The resulting `(x2 * x2) / 20e21` term has been split up in order to avoid overflow of `x2 * x2`.\n            uint256 additiveTerms = 84e27 + (9e3 * x2) + ((x2 / 2e11) * (x2 / 1e11));\n\n            // `differentTerms` is `(- x/2 - x^3/84)`, but positive (will be subtracted later), and scaled by `84e27`.\n            uint256 differentTerms = uint256(x) * (42e15 + (x2 / 1e9));\n\n            // Result needs to be scaled by `1e12`.\n            // NOTE: Can cast to `uint48` because contents can never be larger than `type(uint48).max` for any `x`.\n            //       Max `y` is ~200e12, before falling off. See links above for reference.\n            return uint48(((additiveTerms + differentTerms) * 1e12) / (additiveTerms - differentTerms));\n        }\n    }\n\n    /**\n     * @notice Helper function to convert 12-decimal representation to basis points.\n     * @param  input The input in 12-decimal representation.\n     * @return The output in basis points.\n     */\n    function convertToBasisPoints(uint64 input) internal pure returns (uint40) {\n        unchecked {\n            return uint40((uint256(input) * BPS_SCALED_ONE) / EXP_SCALED_ONE);\n        }\n    }\n\n    /**\n     * @notice Helper function to convert basis points to 12-decimal representation.\n     * @param  input The input in basis points.\n     * @return The output in 12-decimal representation.\n     */\n    function convertFromBasisPoints(uint32 input) internal pure returns (uint64) {\n        unchecked {\n            return uint64((uint256(input) * EXP_SCALED_ONE) / BPS_SCALED_ONE);\n        }\n    }\n}\n"
      },
      "lib/protocol/lib/common/src/interfaces/IERC20Extended.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC20 } from \"./IERC20.sol\";\nimport { IERC3009 } from \"./IERC3009.sol\";\n\n/**\n * @title  An ERC20 token extended with EIP-2612 permits for signed approvals (via EIP-712\n *         and with EIP-1271 compatibility), and extended with EIP-3009 transfer with authorization (via EIP-712).\n * @author M^0 Labs\n * @dev    The additional interface as defined by EIP-2612: https://eips.ethereum.org/EIPS/eip-2612\n */\ninterface IERC20Extended is IERC20, IERC3009 {\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when spender's allowance is not sufficient.\n     * @param  spender    Address that may be allowed to operate on tokens without being their owner.\n     * @param  allowance  Amount of tokens a `spender` is allowed to operate with.\n     * @param  needed     Minimum amount required to perform a transfer.\n     */\n    error InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @notice Revert message emitted when the transferred amount is insufficient.\n     * @param  amount Amount transferred.\n     */\n    error InsufficientAmount(uint256 amount);\n\n    /**\n     * @notice Revert message emitted when the recipient of a token is invalid.\n     * @param  recipient Address of the invalid recipient.\n     */\n    error InvalidRecipient(address recipient);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Approves `spender` to spend up to `amount` of the token balance of `owner`, via a signature.\n     * @param  owner    The address of the account who's token balance is being approved to be spent by `spender`.\n     * @param  spender  The address of an account allowed to spend on behalf of `owner`.\n     * @param  value    The amount of the allowance being approved.\n     * @param  deadline The last block number where the signature is still valid.\n     * @param  v        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     * @param  r        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     * @param  s        An ECDSA secp256k1 signature parameter (EIP-2612 via EIP-712).\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Approves `spender` to spend up to `amount` of the token balance of `owner`, via a signature.\n     * @param  owner     The address of the account who's token balance is being approved to be spent by `spender`.\n     * @param  spender   The address of an account allowed to spend on behalf of `owner`.\n     * @param  value     The amount of the allowance being approved.\n     * @param  deadline  The last block number where the signature is still valid.\n     * @param  signature An arbitrary signature (EIP-712).\n     */\n    function permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the EIP712 typehash used in the encoding of the digest for the permit function.\n    function PERMIT_TYPEHASH() external view returns (bytes32);\n}\n"
      },
      "lib/protocol/lib/common/src/ERC3009.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\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"
      },
      "lib/protocol/src/interfaces/ITTGRegistrar.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  TTG (Two Token Governance) Registrar interface.\n * @author M^0 Labs\n */\ninterface ITTGRegistrar {\n    /**\n     * @notice Key value pair getter.\n     * @param  key The key to get the value of.\n     * @return value The value of the key.\n     */\n    function get(bytes32 key) external view returns (bytes32 value);\n\n    /**\n     * @notice Checks if the list contains the account.\n     * @param  list The list to check.\n     * @param  account The account to check.\n     * @return True if the list contains the account, false otherwise.\n     */\n    function listContains(bytes32 list, address account) external view returns (bool);\n\n    /// @notice Returns the vault contract address.\n    function vault() external view returns (address);\n}\n"
      },
      "lib/protocol/lib/common/src/interfaces/IERC3009.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IStatefulERC712 } from \"./IStatefulERC712.sol\";\n\n/**\n * @title  Transfer via signed authorization following EIP-3009 standard.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-3009: https://eips.ethereum.org/EIPS/eip-3009\n */\ninterface IERC3009 is IStatefulERC712 {\n    /* ============ Events ============ */\n\n    /**\n     * @notice Emitted when an authorization has been canceled.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the canceled authorization.\n     */\n    event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce);\n\n    /**\n     * @notice Emitted when an authorization has been used.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the used authorization.\n     */\n    event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);\n\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Emitted when an authorization has already been used.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the used authorization.\n     */\n    error AuthorizationAlreadyUsed(address authorizer, bytes32 nonce);\n\n    /**\n     * @notice Emitted when an authorization is expired.\n     * @param  timestamp   Timestamp at which the transaction was submitted.\n     * @param  validBefore Timestamp before which the authorization would have been valid.\n     */\n    error AuthorizationExpired(uint256 timestamp, uint256 validBefore);\n\n    /**\n     * @notice Emitted when an authorization is not yet valid.\n     * @param  timestamp  Timestamp at which the transaction was submitted.\n     * @param  validAfter Timestamp after which the authorization will be valid.\n     */\n    error AuthorizationNotYetValid(uint256 timestamp, uint256 validAfter);\n\n    /**\n     * @notice Emitted when the caller of `receiveWithAuthorization` is not the payee.\n     * @param  caller Caller's address.\n     * @param  payee  Payee's address.\n     */\n    error CallerMustBePayee(address caller, address payee);\n\n    /* ============ Interactive Functions ============ */\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  signature   A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes memory signature\n    ) external;\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  r           An ECDSA/secp256k1 signature parameter.\n     * @param  vs          An ECDSA/secp256k1 short signature parameter.\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes32 r,\n        bytes32 vs\n    ) external;\n\n    /**\n     * @notice Execute a transfer with a signed authorization.\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  v           v of the signature.\n     * @param  r           r of the signature.\n     * @param  s           s of the signature.\n     */\n    function transferWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  signature   A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes memory signature\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  r           An ECDSA/secp256k1 signature parameter.\n     * @param  vs          An ECDSA/secp256k1 short signature parameter.\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        bytes32 r,\n        bytes32 vs\n    ) external;\n\n    /**\n     * @notice Receive a transfer with a signed authorization from the payer.\n     * @dev    This has an additional check to ensure that the payee's address matches\n     *         the caller of this function to prevent front-running attacks.\n     *         (See security considerations)\n     * @param  from        Payer's address (Authorizer).\n     * @param  to          Payee's address.\n     * @param  value       Amount to be transferred.\n     * @param  validAfter  The time after which this is valid (unix time).\n     * @param  validBefore The time before which this is valid (unix time).\n     * @param  nonce       Unique nonce.\n     * @param  v           v of the signature.\n     * @param  r           r of the signature.\n     * @param  s           s of the signature.\n     */\n    function receiveWithAuthorization(\n        address from,\n        address to,\n        uint256 value,\n        uint256 validAfter,\n        uint256 validBefore,\n        bytes32 nonce,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  signature  A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  r          An ECDSA/secp256k1 signature parameter.\n     * @param  vs         An ECDSA/secp256k1 short signature parameter.\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, bytes32 r, bytes32 vs) external;\n\n    /**\n     * @notice Attempt to cancel an authorization.\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @param  v          v of the signature.\n     * @param  r          r of the signature.\n     * @param  s          s of the signature.\n     */\n    function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) external;\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the state of an authorization.\n     * @dev    Nonces are randomly generated 32-byte data unique to the authorizer's address\n     * @param  authorizer Authorizer's address.\n     * @param  nonce      Nonce of the authorization.\n     * @return True if the nonce is used.\n     */\n    function authorizationState(address authorizer, bytes32 nonce) external view returns (bool);\n\n    /// @notice Returns `transferWithAuthorization` typehash.\n    function TRANSFER_WITH_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n\n    /// @notice Returns `receiveWithAuthorization` typehash.\n    function RECEIVE_WITH_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n\n    /// @notice Returns `cancelAuthorization` typehash.\n    function CANCEL_AUTHORIZATION_TYPEHASH() external view returns (bytes32);\n}\n"
      },
      "lib/protocol/lib/common/src/StatefulERC712.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\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"
      },
      "lib/protocol/lib/common/src/interfaces/IStatefulERC712.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC712Extended } from \"./IERC712Extended.sol\";\n\n/**\n * @title  Stateful Extension for EIP-712 typed structured data hashing and signing with nonces.\n * @author M^0 Labs\n */\ninterface IStatefulERC712 is IERC712Extended {\n    /* ============ Custom Errors ============ */\n\n    /**\n     * @notice Revert message when a signing account's nonce is not the expected current nonce.\n     * @param  nonce         The nonce used in the signature.\n     * @param  expectedNonce The expected nonce to be used in a signature by the signing account.\n     */\n    error InvalidAccountNonce(uint256 nonce, uint256 expectedNonce);\n\n    /* ============ View/Pure Functions ============ */\n\n    /**\n     * @notice Returns the next nonce to be used in a signature by `account`.\n     * @param  account The address of some account.\n     * @return nonce   The next nonce to be used in a signature by `account`.\n     */\n    function nonces(address account) external view returns (uint256 nonce);\n}\n"
      },
      "lib/protocol/lib/common/src/ERC712Extended.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC712 } from \"./interfaces/IERC712.sol\";\nimport { IERC712Extended } from \"./interfaces/IERC712Extended.sol\";\n\nimport { SignatureChecker } from \"./libs/SignatureChecker.sol\";\n\n/**\n * @title  Typed structured data hashing and signing via EIP-712, extended by EIP-5267.\n * @author M^0 Labs\n * @dev    An abstract implementation to satisfy EIP-712: https://eips.ethereum.org/EIPS/eip-712\n */\nabstract contract ERC712Extended is IERC712Extended {\n    /* ============ Variables ============ */\n\n    /// @dev keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")\n    bytes32 internal constant _EIP712_DOMAIN_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\n\n    /// @dev keccak256(\"1\")\n    bytes32 internal constant _EIP712_VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;\n\n    /// @dev Initial Chain ID set at deployment.\n    uint256 internal immutable _INITIAL_CHAIN_ID;\n\n    /// @dev Initial EIP-712 domain separator set at deployment.\n    bytes32 internal immutable _INITIAL_DOMAIN_SEPARATOR;\n\n    /// @dev The name of the contract.\n    string internal _name;\n\n    /* ============ Constructor ============ */\n\n    /**\n     * @notice Constructs the EIP-712 domain separator.\n     * @param  name_ The name of the contract.\n     */\n    constructor(string memory name_) {\n        _name = name_;\n\n        _INITIAL_CHAIN_ID = block.chainid;\n        _INITIAL_DOMAIN_SEPARATOR = _getDomainSeparator();\n    }\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @inheritdoc IERC712Extended\n    function eip712Domain()\n        external\n        view\n        virtual\n        returns (\n            bytes1 fields_,\n            string memory name_,\n            string memory version_,\n            uint256 chainId_,\n            address verifyingContract_,\n            bytes32 salt_,\n            uint256[] memory extensions_\n        )\n    {\n        return (\n            hex\"0f\", // 01111\n            _name,\n            \"1\",\n            block.chainid,\n            address(this),\n            bytes32(0),\n            new uint256[](0)\n        );\n    }\n\n    /// @inheritdoc IERC712\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return block.chainid == _INITIAL_CHAIN_ID ? _INITIAL_DOMAIN_SEPARATOR : _getDomainSeparator();\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Computes the EIP-712 domain separator.\n     * @return The EIP-712 domain separator.\n     */\n    function _getDomainSeparator() internal view returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    _EIP712_DOMAIN_HASH,\n                    keccak256(bytes(_name)),\n                    _EIP712_VERSION_HASH,\n                    block.chainid,\n                    address(this)\n                )\n            );\n    }\n\n    /**\n     * @dev    Returns the digest to be signed, via EIP-712, given an internal digest (i.e. hash struct).\n     * @param  internalDigest_ The internal digest.\n     * @return The digest to be signed.\n     */\n    function _getDigest(bytes32 internalDigest_) internal view returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR(), internalDigest_));\n    }\n\n    /**\n     * @dev   Revert if the signature is expired.\n     * @param expiry_ Timestamp at which the signature expires or max uint256 for no expiry.\n     */\n    function _revertIfExpired(uint256 expiry_) internal view {\n        if (block.timestamp > expiry_) revert SignatureExpired(expiry_, block.timestamp);\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @dev   We first validate if the signature is a valid ECDSA signature and return early if it is the case.\n     *        Then, we validate if it is a valid ERC-1271 signature, and return early if it is the case.\n     *        If not, we revert with the error from the ECDSA signature validation.\n     * @param signer_    The signer of the signature.\n     * @param digest_    The digest that was signed.\n     * @param signature_ The signature.\n     */\n    function _revertIfInvalidSignature(address signer_, bytes32 digest_, bytes memory signature_) internal view {\n        SignatureChecker.Error error_ = SignatureChecker.validateECDSASignature(signer_, digest_, signature_);\n\n        if (error_ == SignatureChecker.Error.NoError) return;\n\n        if (SignatureChecker.isValidERC1271Signature(signer_, digest_, signature_)) return;\n\n        _revertIfError(error_);\n    }\n\n    /**\n     * @dev    Returns the signer of a signed digest, via EIP-712, and reverts if the signature is invalid.\n     * @param  digest_ The digest that was signed.\n     * @param  v_      v of the signature.\n     * @param  r_      r of the signature.\n     * @param  s_      s of the signature.\n     * @return signer_ The signer of the digest.\n     */\n    function _getSignerAndRevertIfInvalidSignature(\n        bytes32 digest_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) internal pure returns (address signer_) {\n        SignatureChecker.Error error_;\n\n        (error_, signer_) = SignatureChecker.recoverECDSASigner(digest_, v_, r_, s_);\n\n        _revertIfError(error_);\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @param signer_ The signer of the signature.\n     * @param digest_ The digest that was signed.\n     * @param r_      An ECDSA/secp256k1 signature parameter.\n     * @param vs_     An ECDSA/secp256k1 short signature parameter.\n     */\n    function _revertIfInvalidSignature(address signer_, bytes32 digest_, bytes32 r_, bytes32 vs_) internal pure {\n        _revertIfError(SignatureChecker.validateECDSASignature(signer_, digest_, r_, vs_));\n    }\n\n    /**\n     * @dev   Revert if the signature is invalid.\n     * @param signer_ The signer of the signature.\n     * @param digest_ The digest that was signed.\n     * @param v_      v of the signature.\n     * @param r_      r of the signature.\n     * @param s_      s of the signature.\n     */\n    function _revertIfInvalidSignature(\n        address signer_,\n        bytes32 digest_,\n        uint8 v_,\n        bytes32 r_,\n        bytes32 s_\n    ) internal pure {\n        _revertIfError(SignatureChecker.validateECDSASignature(signer_, digest_, v_, r_, s_));\n    }\n\n    /**\n     * @dev   Revert if error.\n     * @param error_ The SignatureChecker Error enum.\n     */\n    function _revertIfError(SignatureChecker.Error error_) private pure {\n        if (error_ == SignatureChecker.Error.NoError) return;\n        if (error_ == SignatureChecker.Error.InvalidSignature) revert InvalidSignature();\n        if (error_ == SignatureChecker.Error.InvalidSignatureLength) revert InvalidSignatureLength();\n        if (error_ == SignatureChecker.Error.InvalidSignatureS) revert InvalidSignatureS();\n        if (error_ == SignatureChecker.Error.InvalidSignatureV) revert InvalidSignatureV();\n        if (error_ == SignatureChecker.Error.SignerMismatch) revert SignerMismatch();\n\n        revert InvalidSignature();\n    }\n}\n"
      },
      "lib/protocol/lib/common/src/interfaces/IERC712Extended.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC712 } from \"./IERC712.sol\";\n\n/**\n * @title  EIP-712 extended by EIP-5267.\n * @author M^0 Labs\n * @dev    The additional interface as defined by EIP-5267: https://eips.ethereum.org/EIPS/eip-5267\n */\ninterface IERC712Extended is IERC712 {\n    /* ============ Events ============ */\n\n    /// @notice MAY be emitted to signal that the domain could have changed.\n    event EIP712DomainChanged();\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the fields and values that describe the domain separator used by this contract for EIP-712.\n    function eip712Domain()\n        external\n        view\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        );\n}\n"
      },
      "lib/protocol/lib/common/src/interfaces/IERC712.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  Typed structured data hashing and signing via EIP-712.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-712: https://eips.ethereum.org/EIPS/eip-712\n */\ninterface IERC712 {\n    /* ============ Custom Errors ============ */\n\n    /// @notice Revert message when an invalid signature is detected.\n    error InvalidSignature();\n\n    /// @notice Revert message when a signature with invalid length is detected.\n    error InvalidSignatureLength();\n\n    /// @notice Revert message when the S portion of a signature is invalid.\n    error InvalidSignatureS();\n\n    /// @notice Revert message when the V portion of a signature is invalid.\n    error InvalidSignatureV();\n\n    /**\n     * @notice Revert message when a signature is being used beyond its deadline (i.e. expiry).\n     * @param  deadline  The deadline of the signature.\n     * @param  timestamp The current timestamp.\n     */\n    error SignatureExpired(uint256 deadline, uint256 timestamp);\n\n    /// @notice Revert message when a recovered signer does not match the account being purported to have signed.\n    error SignerMismatch();\n\n    /* ============ View/Pure Functions ============ */\n\n    /// @notice Returns the EIP712 domain separator used in the encoding of a signed digest.\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "lib/protocol/lib/common/src/libs/SignatureChecker.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\nimport { IERC1271 } from \"../interfaces/IERC1271.sol\";\n\n/**\n * @title  A library to handle ECDSA/secp256k1 and ERC1271 signatures, individually or in arbitrarily in combination.\n * @author M^0 Labs\n */\nlibrary SignatureChecker {\n    /* ============ Enums ============ */\n\n    /**\n     * @notice An enum representing the possible errors that can be emitted during signature validation.\n     * @param  NoError                No error occurred during signature validation.\n     * @param  InvalidSignature       The signature is invalid.\n     * @param  InvalidSignatureLength The signature length is invalid.\n     * @param  InvalidSignatureS      The signature parameter S is invalid.\n     * @param  InvalidSignatureV      The signature parameter V is invalid.\n     * @param  SignerMismatch         The signer does not match the recovered signer.\n     */\n    enum Error {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV,\n        SignerMismatch\n    }\n\n    /* ============ Internal View/Pure Functions ============ */\n\n    /**\n     * @dev    Returns whether a signature is valid (ECDSA/secp256k1 or ERC1271) for a signer and digest.\n     * @dev    Signatures must not be used as unique identifiers since the `ecrecover` EVM opcode\n     *         allows for malleable (non-unique) signatures.\n     *         See https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-4h98-2769-gh6h\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array signature.\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidSignature(address signer, bytes32 digest, bytes memory signature) internal view returns (bool) {\n        return isValidECDSASignature(signer, digest, signature) || isValidERC1271Signature(signer, digest, signature);\n    }\n\n    /**\n     * @dev    Returns whether an ERC1271 signature is valid for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ERC1271 signature.\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidERC1271Signature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal view returns (bool) {\n        (bool success, bytes memory result) = signer.staticcall(\n            abi.encodeCall(IERC1271.isValidSignature, (digest, signature))\n        );\n\n        return\n            success &&\n            result.length >= 32 &&\n            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector);\n    }\n\n    /**\n     * @dev    Decodes an ECDSA/secp256k1 signature from a byte array to standard v, r, and s parameters.\n     * @param  signature A byte array ECDSA/secp256k1 signature.\n     * @return v         An ECDSA/secp256k1 signature parameter.\n     * @return r         An ECDSA/secp256k1 signature parameter.\n     * @return s         An ECDSA/secp256k1 signature parameter.\n     */\n    function decodeECDSASignature(bytes memory signature) internal pure returns (uint8 v, bytes32 r, bytes32 s) {\n        // ecrecover takes the signature parameters, and they can be decoded using assembly.\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := mload(add(signature, 0x20))\n            s := mload(add(signature, 0x40))\n            v := byte(0, mload(add(signature, 0x60)))\n        }\n    }\n\n    /**\n     * @dev    Decodes an ECDSA/secp256k1 short signature as defined by EIP2098\n     *         from a byte array to standard v, r, and s parameters.\n     * @param  signature A byte array ECDSA/secp256k1 short signature.\n     * @return r         An ECDSA/secp256k1 signature parameter.\n     * @return vs        An ECDSA/secp256k1 short signature parameter.\n     */\n    function decodeShortECDSASignature(bytes memory signature) internal pure returns (bytes32 r, bytes32 vs) {\n        // ecrecover takes the signature parameters, and they can be decoded using assembly.\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := mload(add(signature, 0x20))\n            vs := mload(add(signature, 0x40))\n        }\n    }\n\n    /**\n     * @dev    Returns whether an ECDSA/secp256k1 signature is valid for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ECDSA/secp256k1 signature (encoded r, s, v).\n     * @return           Whether the signature is valid or not.\n     */\n    function isValidECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal pure returns (bool) {\n        if (signature.length == 64) {\n            (bytes32 r, bytes32 vs) = decodeShortECDSASignature(signature);\n            return isValidECDSASignature(signer, digest, r, vs);\n        }\n\n        return validateECDSASignature(signer, digest, signature) == Error.NoError;\n    }\n\n    /**\n     * @dev    Returns whether an ECDSA/secp256k1 short signature is valid for a signer and digest.\n     * @param  signer  The address of the account purported to have signed.\n     * @param  digest  The hash of the data that was signed.\n     * @param  r       An ECDSA/secp256k1 signature parameter.\n     * @param  vs      An ECDSA/secp256k1 short signature parameter.\n     * @return         Whether the signature is valid or not.\n     */\n    function isValidECDSASignature(address signer, bytes32 digest, bytes32 r, bytes32 vs) internal pure returns (bool) {\n        return validateECDSASignature(signer, digest, r, vs) == Error.NoError;\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 signature for some digest.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ECDSA/secp256k1 signature.\n     * @return           An error, if any, that occurred during the signer recovery.\n     * @return           The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(bytes32 digest, bytes memory signature) internal pure returns (Error, address) {\n        if (signature.length != 65) return (Error.InvalidSignatureLength, address(0));\n\n        (uint8 v, bytes32 r, bytes32 s) = decodeECDSASignature(signature);\n\n        return recoverECDSASigner(digest, v, r, s);\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 short signature for some digest.\n     * @dev    See https://eips.ethereum.org/EIPS/eip-2098\n     * @param  digest The hash of the data that was signed.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  vs     An ECDSA/secp256k1 short signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     * @return        The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(bytes32 digest, bytes32 r, bytes32 vs) internal pure returns (Error, address) {\n        unchecked {\n            // We do not check for an overflow here since the shift operation results in 0 or 1.\n            uint8 v = uint8((uint256(vs) >> 255) + 27);\n            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n            return recoverECDSASigner(digest, v, r, s);\n        }\n    }\n\n    /**\n     * @dev    Returns the signer of an ECDSA/secp256k1 signature for some digest.\n     * @param  digest The hash of the data that was signed.\n     * @param  v      An ECDSA/secp256k1 signature parameter.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  s      An ECDSA/secp256k1 signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     * @return signer The address of the account recovered form the signature (0 if error).\n     */\n    function recoverECDSASigner(\n        bytes32 digest,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (Error, address signer) {\n        // Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}.\n        if (uint256(s) > uint256(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0))\n            return (Error.InvalidSignatureS, address(0));\n\n        if (v != 27 && v != 28) return (Error.InvalidSignatureV, address(0));\n\n        signer = ecrecover(digest, v, r, s);\n\n        return (signer == address(0)) ? (Error.InvalidSignature, address(0)) : (Error.NoError, signer);\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 signature for a signer and digest.\n     * @param  signer    The address of the account purported to have signed.\n     * @param  digest    The hash of the data that was signed.\n     * @param  signature A byte array ERC1271 signature.\n     * @return           An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes memory signature\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, signature);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 short signature for a signer and digest.\n     * @param  signer The address of the account purported to have signed.\n     * @param  digest The hash of the data that was signed.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  vs     An ECDSA/secp256k1 short signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, r, vs);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error, if any, in validating an ECDSA/secp256k1 signature for a signer and digest.\n     * @param  signer The address of the account purported to have signed.\n     * @param  digest The hash of the data that was signed.\n     * @param  v      An ECDSA/secp256k1 signature parameter.\n     * @param  r      An ECDSA/secp256k1 signature parameter.\n     * @param  s      An ECDSA/secp256k1 signature parameter.\n     * @return        An error, if any, that occurred during the signer recovery.\n     */\n    function validateECDSASignature(\n        address signer,\n        bytes32 digest,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (Error) {\n        (Error recoverError, address recoveredSigner) = recoverECDSASigner(digest, v, r, s);\n\n        return (recoverError == Error.NoError) ? validateRecoveredSigner(signer, recoveredSigner) : recoverError;\n    }\n\n    /**\n     * @dev    Returns an error if `signer` is not `recoveredSigner`.\n     * @param  signer          The address of the some signer.\n     * @param  recoveredSigner The address of the some recoveredSigner.\n     * @return                 An error if `signer` is not `recoveredSigner`.\n     */\n    function validateRecoveredSigner(address signer, address recoveredSigner) internal pure returns (Error) {\n        return (signer == recoveredSigner) ? Error.NoError : Error.SignerMismatch;\n    }\n}\n"
      },
      "lib/protocol/lib/common/src/interfaces/IERC1271.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.23;\n\n/**\n * @title  Standard Signature Validation Method for Contracts via EIP-1271.\n * @author M^0 Labs\n * @dev    The interface as defined by EIP-1271: https://eips.ethereum.org/EIPS/eip-1271\n */\ninterface IERC1271 {\n    /**\n     * @dev    Returns a specific magic value if the provided signature is valid for the provided digest.\n     * @param  digest     Hash of the data purported to have been signed.\n     * @param  signature  Signature byte array associated with the digest.\n     * @return magicValue Magic value 0x1626ba7e if the signature is valid.\n     */\n    function isValidSignature(bytes32 digest, bytes memory signature) external view returns (bytes4 magicValue);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "common/=lib/protocol/lib/common/src/",
        "contract-test-utils/=lib/ttg/lib/erc20-helper/lib/contract-test-utils/contracts/",
        "ds-test/=lib/protocol/lib/solmate/lib/ds-test/src/",
        "erc20-helper/=lib/ttg/lib/erc20-helper/src/",
        "forge-std/=lib/forge-std/src/",
        "protocol/=lib/protocol/",
        "solmate/=lib/protocol/lib/solmate/src/",
        "ttg/=lib/ttg/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 999999
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "shanghai",
      "viaIR": false,
      "libraries": {}
    }
  }}