{"file_path":"contracts/globalMarkets/tokenManager/GMTokenManager.sol","creation_status":"success","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\n\npragma solidity 0.8.16;\n\nimport \"contracts/globalMarkets/tokenManager/issuanceHours/IIssuanceHours.sol\";\nimport \"contracts/xManager/interfaces/IOndoIDRegistry.sol\";\nimport \"contracts/xManager/interfaces/IOndoRateLimiter.sol\";\nimport \"contracts/interfaces/IRWALike.sol\";\nimport \"contracts/globalMarkets/tokenManager/IGMTokenManagerErrors.sol\";\nimport \"contracts/globalMarkets/tokenManager/IGMTokenManagerEvents.sol\";\nimport \"contracts/external/openzeppelin/contracts/access/AccessControlEnumerable.sol\";\nimport \"contracts/external/openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"contracts/external/openzeppelin/contracts/token/SafeERC20.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/cryptography/EIP712.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"contracts/globalMarkets/tokenManager/IGMTokenManager.sol\";\nimport \"contracts/globalMarkets/tokenManager/sanityCheckOracle/IOndoSanityCheckOracle.sol\";\nimport \"contracts/globalMarkets/USDonManager/IUSDonManager.sol\";\n\n/**\n * @title  GMTokenManager\n * @author Ondo Finance\n * @notice Contract for managing tokenized equity assets\n * @notice The GMTokenManager contract contains the core logic for processing minting\n *         and redemptions of GM tokens.\n *         The responsibilities of this contract are:\n *          - Verifying attestation signatures\n *          - Calculating the amount of GM tokens and USDon to mint and burn\n *            based on the quote attestation that was received\n *          - Performing appropriate sanity checks on the quote attestation\n *          - Enforcing the minimum deposit and redemption amounts and ensuring the\n *            quote price is in line with the rough oracle price\n *          - Ensuring users are registered with the OndoIDRegistry\n *          - Checking user-specific and global rate limits\n */\ncontract GMTokenManager is\n  EIP712,\n  IGMTokenManager,\n  IGMTokenManagerEvents,\n  IGMTokenManagerErrors,\n  ReentrancyGuard,\n  AccessControlEnumerable\n{\n  using SafeERC20 for IERC20;\n\n  /// The identifier address used in OndoIDRegistry to validate KYC for all GM token issuance\n  address public gmIdentifier =\n    address(uint160(uint256(keccak256(abi.encodePacked(\"global_markets\")))));\n\n  /// Role for signing attestations\n  bytes32 public constant ATTESTATION_SIGNER_ROLE =\n    keccak256(\"ATTESTATION_SIGNER_ROLE\");\n\n  /// Type hash for EIP-712 quote signatures\n  bytes32 public constant QUOTE_TYPEHASH =\n    keccak256(\n      \"Quote(uint256 chainId,uint256 attestationId,bytes32 userId,address asset,uint256 price,uint256 quantity,uint256 expiration,uint8 side,bytes32 additionalData)\"\n    );\n\n  /// Mapping of attestation IDs to whether they have been redeemed\n  mapping(uint256 => bool) public executedAttestationIds;\n\n  /// Monotonically increasing ID for each execution of a quote\n  uint256 public executionId = 0;\n\n  /// The decimals normalizer for the GM token\n  uint256 public constant GM_NORMALIZER = 1e18;\n\n  /// Role to configure the contract\n  bytes32 public constant CONFIGURER_ROLE = keccak256(\"CONFIGURER_ROLE\");\n\n  /// Role to pause minting and redemptions\n  bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n  /// Role to unpause functionality\n  bytes32 public constant UNPAUSER_ROLE = keccak256(\"UNPAUSER_ROLE\");\n\n  /// Role to manually service a mint of GM tokens\n  bytes32 public constant ADMIN_MINT_ROLE = keccak256(\"ADMIN_MINT_ROLE\");\n\n  /// The token that can be used to subscribe to a GM token and can be received when redeeming a GM token\n  address public immutable usdon;\n\n  /// The address of the USDon manager used for swapping with other tokens\n  IUSDonManager public usdonManager;\n\n  /**\n   * @notice Minimum USD amount required to subscribe to a GM token, denoted in USD with 18\n   *         decimals.\n   */\n  uint256 public minimumDepositUSD;\n\n  /**\n   * @notice Minimum USD amount required to perform an GM token redemption to be allowed,\n   *         denoted in USD with 18 decimals\n   */\n  uint256 public minimumRedemptionUSD;\n\n  /// Whether mints are paused for this contract\n  bool public globalMintingPaused;\n\n  /// Whether redemptions are paused for this contract\n  bool public globalRedeemingPaused;\n\n  /// Whether mints are paused for a specific gm asset\n  mapping(address => bool) public gmTokenMintingPaused;\n\n  /// Whether redemptions are paused for a specific gm asset\n  mapping(address => bool) public gmTokenRedemptionsPaused;\n\n  /// The `OndoIDRegistry` contract address\n  IOndoIDRegistry public ondoIDRegistry;\n\n  /// The `OndoRateLimiter` contract address\n  IOndoRateLimiter public ondoRateLimiter;\n\n  /// The `IssuanceHours` contract for managing market hours\n  IIssuanceHours public issuanceHours;\n\n  /// The `OndoSanityCheckOracle` contract for validating the price of the GM token\n  IOndoSanityCheckOracle public sanityCheckOracle;\n\n  /// Map of all GM tokens that are accepted for minting and redemptions\n  mapping(address => bool) public gmTokenAccepted;\n\n  /**\n   * @param _defaultAdmin         The default admin role for the contract\n   * @param _usdon                The address of the USDon token used for minting and redemptions\n   * @param _minimumDepositUSD    The minimum subscription amount, denoted in USD with 18 decimals\n   * @param _minimumRedemptionUSD The minimum redemption amount, denoted in USD with 18 decimals\n   */\n  constructor(\n    address _defaultAdmin,\n    address _usdon,\n    uint256 _minimumDepositUSD,\n    uint256 _minimumRedemptionUSD\n  ) EIP712(\"OndoGMTokenManager\", \"1\") {\n    if (_usdon == address(0)) revert USDonAddressCantBeZero();\n    usdon = _usdon;\n    minimumDepositUSD = _minimumDepositUSD;\n    minimumRedemptionUSD = _minimumRedemptionUSD;\n    _grantRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);\n  }\n\n  /**\n   * @notice Called by users to mint GM tokens with a quote attestation using USDon\n   * @param  quote              The quote to mint GM tokens with\n   * @param  signature          The signature of the quote attestation\n   * @param  depositToken       The token the user would like to deposit in return for GM Tokens.\n   *                            If not USDon, this will be reliant on the ability to swap for USDon in the USDonManager\n   * @param  depositTokenAmount The amount of depositToken the user wishes to spend to purchase USDon atomically in the transaction\n   * @return The amount of GM tokens minted to the user\n   * @dev    If the deposit token is not USDon and the depositTokenAmount is not enough to swap for USDon\n   *         worth quantity * price as specified in the quote, the transaction will fail as the `mintUSDonValue`\n   *         is passed in to the minimum RWA received field in `subscribe`.\n   */\n  function mintWithAttestation(\n    Quote calldata quote,\n    bytes memory signature,\n    address depositToken,\n    uint256 depositTokenAmount\n  )\n    public\n    override\n    nonReentrant\n    whenMintingNotPaused(quote.asset)\n    returns (uint256)\n  {\n    if (depositToken == address(0)) revert TokenAddressCantBeZero();\n    if (quote.side != QuoteSide.BUY) revert InvalidQuoteSide();\n\n    bytes32 userId = ondoIDRegistry.getRegisteredID(gmIdentifier, _msgSender());\n    if (userId == bytes32(0)) revert UserNotRegistered();\n\n    _verifyQuote(quote, signature, userId);\n    executedAttestationIds[quote.attestationId] = true;\n\n    // USD values are normalized to 18 decimals\n    uint256 mintUSDonValue = (quote.quantity * quote.price) / GM_NORMALIZER;\n    if (mintUSDonValue < minimumDepositUSD) revert DepositAmountTooSmall();\n\n    ondoRateLimiter.checkAndUpdateRateLimit(\n      IOndoRateLimiter.TransactionType.SUBSCRIPTION,\n      quote.asset,\n      userId,\n      mintUSDonValue\n    );\n\n    // Transfer usdon into the contract\n    if (depositToken == address(usdon)) {\n      IERC20(usdon).safeTransferFrom(\n        _msgSender(),\n        address(this),\n        mintUSDonValue\n      );\n    } else {\n      if (address(usdonManager) == address(0)) revert USDonManagerNotEnabled();\n      IERC20(depositToken).safeTransferFrom(\n        _msgSender(),\n        address(this),\n        depositTokenAmount\n      );\n      IERC20(depositToken).forceApprove(\n        address(usdonManager),\n        depositTokenAmount\n      );\n      uint256 receivedOnUsd = usdonManager.subscribe(\n        depositToken,\n        depositTokenAmount,\n        mintUSDonValue\n      );\n\n      // If the deposit token is not USDon, we need to refund the user if they sent more than\n      // the required amount of USDon to mint the GM tokens\n      uint256 refund = receivedOnUsd - mintUSDonValue;\n      if (refund > 0) {\n        IERC20(usdon).safeTransfer(_msgSender(), refund);\n      }\n    }\n\n    IRWALike(usdon).burn(mintUSDonValue);\n\n    // actually mint the token to the user\n    IRWALike(quote.asset).mint(_msgSender(), quote.quantity);\n\n    _emitTradeExecuted(quote);\n\n    return quote.quantity;\n  }\n\n  /**\n   * @notice Called by users to redeem GM tokens for USDon\n   * @param  quote                The quote to redeem GM tokens with\n   * @param  signature            The signature of the quote attestation\n   * @param  receiveToken         The token the user would like to receive. If it is not USDon,\n   *                              transaction success will depend on liquidity in USDonManager\n   * @param  minimumReceiveAmount The minimum amount of tokens the user would like to receive\n   *                              - ONLY applicable if the user requests a non-USDon token\n   * @return The amount of USDon minted\n   */\n  function redeemWithAttestation(\n    Quote calldata quote,\n    bytes memory signature,\n    address receiveToken,\n    uint256 minimumReceiveAmount\n  )\n    public\n    override\n    nonReentrant\n    whenRedeemNotPaused(quote.asset)\n    returns (uint256)\n  {\n    if (receiveToken == address(0)) revert TokenAddressCantBeZero();\n    if (quote.side != QuoteSide.SELL) revert InvalidQuoteSide();\n\n    bytes32 userId = ondoIDRegistry.getRegisteredID(gmIdentifier, _msgSender());\n    if (userId == bytes32(0)) revert UserNotRegistered();\n\n    _verifyQuote(quote, signature, userId);\n    executedAttestationIds[quote.attestationId] = true;\n\n    // burn the GM tokens\n    IERC20(quote.asset).safeTransferFrom(\n      _msgSender(),\n      address(this),\n      quote.quantity\n    );\n    IRWALike(quote.asset).burn(quote.quantity);\n\n    // USD values are normalized to 18 decimals\n    uint256 redemptionUSDonValue = (quote.quantity * quote.price) /\n      GM_NORMALIZER;\n\n    if (redemptionUSDonValue < minimumRedemptionUSD)\n      revert RedemptionAmountTooSmall();\n\n    ondoRateLimiter.checkAndUpdateRateLimit(\n      IOndoRateLimiter.TransactionType.REDEMPTION,\n      quote.asset,\n      userId,\n      redemptionUSDonValue\n    );\n\n    // Mint USDon to the contract\n    IRWALike(usdon).mint(address(this), redemptionUSDonValue);\n\n    if (receiveToken == address(usdon)) {\n      IERC20(usdon).safeTransfer(_msgSender(), redemptionUSDonValue);\n    } else {\n      if (address(usdonManager) == address(0)) revert USDonManagerNotEnabled();\n      IERC20(usdon).approve(address(usdonManager), redemptionUSDonValue);\n      uint256 receiveAmount = usdonManager.redeem(\n        redemptionUSDonValue,\n        receiveToken,\n        minimumReceiveAmount\n      );\n      IERC20(receiveToken).safeTransfer(_msgSender(), receiveAmount);\n    }\n\n    _emitTradeExecuted(quote);\n\n    return redemptionUSDonValue;\n  }\n\n  /**\n   * @notice Verifies the signature of the quote\n   * @param  quote     The quote to verify\n   * @param  signature The signature to verify\n   * @param  userId    The user ID of the user executing the quote\n   */\n  function _verifyQuote(\n    Quote calldata quote,\n    bytes memory signature,\n    bytes32 userId\n  ) internal {\n    // Ensure the attestation isn't being reused\n    if (executedAttestationIds[quote.attestationId])\n      revert AttestationAlreadyExecuted();\n\n    if (block.timestamp > quote.expiration) revert AttestationExpired();\n\n    if (userId != quote.userId) revert UserIdMismatch(userId, quote.userId);\n\n    issuanceHours.checkIsValidHours();\n\n    sanityCheckOracle.validatePrice(quote.asset, quote.price);\n\n    if (gmTokenAccepted[quote.asset] == false) revert GMTokenNotRegistered();\n\n    if (quote.chainId != block.chainid) revert InvalidChainId();\n\n    bytes32 digest = _hashTypedDataV4(\n      keccak256(\n        abi.encode(\n          QUOTE_TYPEHASH,\n          quote.chainId,\n          quote.attestationId,\n          quote.userId,\n          quote.asset,\n          quote.price,\n          quote.quantity,\n          quote.expiration,\n          quote.side,\n          quote.additionalData\n        )\n      )\n    );\n\n    address signer = ECDSA.recover(digest, signature);\n    if (!hasRole(ATTESTATION_SIGNER_ROLE, signer))\n      revert InvalidAttestationSigner();\n  }\n\n  /**\n   * @notice Emits a `TradeExecuted` event and increments the `executionId`\n   * @param  quote The quote to emit the event for\n   * @dev    The only purpose of this is to prevent stack too deep errors from unpacking the large struct.\n   *         Increments executionId before emitting to provide a unique ID for each trade.\n   */\n  function _emitTradeExecuted(Quote calldata quote) internal {\n    emit TradeExecuted(\n      ++executionId,\n      quote.attestationId,\n      quote.chainId,\n      quote.userId,\n      quote.side,\n      quote.asset,\n      quote.price,\n      quote.quantity,\n      quote.expiration,\n      quote.additionalData\n    );\n  }\n\n  /**\n   * @notice Admin function to service a subscription whose corresponding deposit been made outside\n   *         of this contracts system.\n   * @param  gmToken       The address of the GM token to mint\n   * @param  recipient     The address to send the GM tokens to\n   * @param  gmTokenAmount The amount of GM tokens to mint and/or transfer\n   * @param  metadata      Additional metadata to emit with the subscription\n   */\n  function adminProcessMint(\n    address gmToken,\n    address recipient,\n    uint256 gmTokenAmount,\n    bytes32 metadata\n  ) external whenMintingNotPaused(gmToken) onlyRole(ADMIN_MINT_ROLE) {\n    if (!gmTokenAccepted[gmToken]) revert GMTokenNotRegistered();\n\n    bytes32 userId = ondoIDRegistry.getRegisteredID(gmIdentifier, recipient);\n    if (userId == bytes32(0)) revert UserNotRegistered();\n\n    // Actually mint the token to the user\n    IRWALike(gmToken).mint(recipient, gmTokenAmount);\n\n    emit AdminMint(recipient, userId, gmToken, gmTokenAmount, metadata);\n  }\n\n  /**\n   * @notice Sets the `IssuanceHours` contract\n   * @param  _issuanceHours The `IssuanceHours` contract address\n   */\n  function setIssuanceHours(\n    address _issuanceHours\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    if (_issuanceHours == address(0)) revert IssuanceHoursAddressCantBeZero();\n    emit IssuanceHoursSet(address(issuanceHours), _issuanceHours);\n    issuanceHours = IIssuanceHours(_issuanceHours);\n  }\n\n  /**\n   * @notice Sets the `OndoSanityCheckOracle` contract\n   * @param  _sanityCheckOracle The new `OndoSanityCheckOracle` contract address\n   */\n  function setSanityCheckOracle(\n    address _sanityCheckOracle\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    if (_sanityCheckOracle == address(0))\n      revert SanityCheckOracleAddressCantBeZero();\n    emit OndoSanityCheckOracleSet(\n      address(sanityCheckOracle),\n      _sanityCheckOracle\n    );\n    sanityCheckOracle = IOndoSanityCheckOracle(_sanityCheckOracle);\n  }\n\n  /**\n   * @notice Sets the `OndoIDRegistry` contract\n   * @param  _ondoIDRegistry The `OndoIDRegistry` contract address\n   */\n  function setOndoIDRegistry(\n    address _ondoIDRegistry\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    if (_ondoIDRegistry == address(0)) revert IDRegistryAddressCantBeZero();\n    emit OndoIDRegistrySet(address(ondoIDRegistry), _ondoIDRegistry);\n    ondoIDRegistry = IOndoIDRegistry(_ondoIDRegistry);\n    // Ensure that the `OndoIDRegistry` interface is supported\n    ondoIDRegistry.getRegisteredID(gmIdentifier, address(this));\n  }\n\n  /**\n   * @notice Sets the `OndoRateLimiter` contract\n   * @param  _ondoRateLimiter The `OndoRateLimiter` contract address\n   */\n  function setOndoRateLimiter(\n    address _ondoRateLimiter\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    if (_ondoRateLimiter == address(0)) revert RateLimiterAddressCantBeZero();\n    emit OndoRateLimiterSet(address(ondoRateLimiter), _ondoRateLimiter);\n    ondoRateLimiter = IOndoRateLimiter(_ondoRateLimiter);\n  }\n\n  /**\n   * @notice Sets the `USDonManager` contract\n   * @param  _usdonManager The `USDonManager` contract address\n   */\n  function setUSDonManager(\n    address _usdonManager\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    emit USDonManagerSet(address(usdonManager), _usdonManager);\n    usdonManager = IUSDonManager(_usdonManager);\n  }\n\n  /**\n   * @notice Sets whether a token is accepted for mints and redemptions on this contract\n   * @param  token    The address of the token\n   * @param  accepted Whether the token is accepted for mints and redemptions\n   */\n  function setGMTokenRegistrationStatus(\n    address token,\n    bool accepted\n  ) external onlyRole(CONFIGURER_ROLE) {\n    if (token == address(0)) revert TokenAddressCantBeZero();\n    gmTokenAccepted[token] = accepted;\n    emit GMTokenRegistered(token, accepted);\n  }\n\n  /**\n   * @notice Sets the minimum amount required for a subscription\n   * @param  _minimumDepositUSD The minimum amount required to subscribe, denoted in\n   *                            USD with 18 decimals\n   */\n  function setMinimumDepositAmount(\n    uint256 _minimumDepositUSD\n  ) external onlyRole(CONFIGURER_ROLE) {\n    emit MinimumDepositAmountSet(minimumDepositUSD, _minimumDepositUSD);\n    minimumDepositUSD = _minimumDepositUSD;\n  }\n\n  /**\n   * @notice Sets the minimum amount to redeem\n   * @param  _minimumRedemptionUSD The minimum amount required to redeem,\n   *                               denoted in USD with 18.\n   */\n  function setMinimumRedemptionAmount(\n    uint256 _minimumRedemptionUSD\n  ) external onlyRole(CONFIGURER_ROLE) {\n    emit MinimumRedemptionAmountSet(\n      minimumRedemptionUSD,\n      _minimumRedemptionUSD\n    );\n    minimumRedemptionUSD = _minimumRedemptionUSD;\n  }\n\n  /**\n   * @notice Rescue and transfer tokens locked in this contract\n   * @param  token  The address of the token\n   * @param  to     The address of the recipient\n   * @param  amount The amount of token to transfer\n   */\n  function retrieveTokens(\n    address token,\n    address to,\n    uint256 amount\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    IERC20(token).safeTransfer(to, amount);\n  }\n\n  /**\n   * @notice Returns the domain separator for EIP712\n   * @return The domain separator\n   */\n  function getDomainSeparator() public view returns (bytes32) {\n    return _domainSeparatorV4();\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                          Pause/Unpause\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Globally pause the minting functionality\n   */\n  function pauseGlobalMints() external onlyRole(PAUSER_ROLE) {\n    globalMintingPaused = true;\n    emit GlobalMintingPaused();\n  }\n\n  /**\n   * @notice Globally unpause the minting functionality\n   */\n  function unpauseGlobalMints() external onlyRole(UNPAUSER_ROLE) {\n    globalMintingPaused = false;\n    emit GlobalMintingUnpaused();\n  }\n\n  /**\n   * @notice Globally pause the redeem functionality\n   */\n  function pauseGlobalRedeems() external onlyRole(PAUSER_ROLE) {\n    globalRedeemingPaused = true;\n    emit GlobalRedeemingPaused();\n  }\n\n  /**\n   * @notice Globally unpause the redeem functionality\n   */\n  function unpauseGlobalRedeems() external onlyRole(UNPAUSER_ROLE) {\n    globalRedeemingPaused = false;\n    emit GlobalRedeemingUnpaused();\n  }\n\n  /**\n   * @notice Pauses minting for a specific GM token\n   * @param  gmToken The address of the GM token\n   */\n  function pauseGMTokenMints(address gmToken) external onlyRole(PAUSER_ROLE) {\n    gmTokenMintingPaused[gmToken] = true;\n    emit GMTokenMintingPaused(gmToken);\n  }\n\n  /**\n   * @notice Unpauses minting for a specific GM token\n   * @param  gmToken The address of the GM token\n   */\n  function unpauseGMTokenMints(\n    address gmToken\n  ) external onlyRole(UNPAUSER_ROLE) {\n    gmTokenMintingPaused[gmToken] = false;\n    emit GMTokenMintingUnpaused(gmToken);\n  }\n\n  /**\n   * @notice Pauses redemption for a specific GM token\n   * @param  gmToken The address of the GM token\n   */\n  function pauseGMTokenRedemptions(\n    address gmToken\n  ) external onlyRole(PAUSER_ROLE) {\n    gmTokenRedemptionsPaused[gmToken] = true;\n    emit GMTokenRedeemingPaused(gmToken);\n  }\n\n  /**\n   * @notice Unpauses redemption for a specific GM token\n   * @param  gmToken The address of the GM token\n   */\n  function unpauseGMTokenRedemptions(\n    address gmToken\n  ) external onlyRole(UNPAUSER_ROLE) {\n    gmTokenRedemptionsPaused[gmToken] = false;\n    emit GMTokenRedeemingUnpaused(gmToken);\n  }\n\n  /**\n   * @notice Ensure that the subscribe functionality is not paused\n   * @param  gmToken The address of the GM token to check\n   * @dev    Reverts if either global minting or token-specific minting is paused\n   */\n  modifier whenMintingNotPaused(address gmToken) {\n    if (globalMintingPaused) revert GlobalMintsPaused();\n    if (gmTokenMintingPaused[gmToken]) revert GMTokenMintsPaused();\n    _;\n  }\n\n  /**\n   * @notice Ensure that the redeem functionality is not paused\n   * @param  gmToken The address of the GM token to check\n   * @dev    Reverts if either global redemptions or token-specific redemptions are paused\n   */\n  modifier whenRedeemNotPaused(address gmToken) {\n    if (globalRedeemingPaused) revert GlobalRedemptionsPaused();\n    if (gmTokenRedemptionsPaused[gmToken]) revert GMTokenRedemptionsPaused();\n    _;\n  }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106103275760003560e01c80637b0e1c57116101b8578063b28996b511610104578063e63ab1e9116100a2578063ed24911d1161007c578063ed24911d1461073d578063ed2a354014610745578063f758161514610758578063fb1bb9de1461077f57600080fd5b8063e63ab1e914610708578063eb27fa531461071d578063ebaf3f211461072a57600080fd5b8063c7f8e171116100de578063c7f8e171146106c0578063c875edf6146106cf578063ca15c873146106e2578063d547741f146106f557600080fd5b8063b28996b514610663578063bd5d370c14610686578063c768b145146106ad57600080fd5b80639010d07c11610171578063a217fddf1161014b578063a217fddf14610620578063aab483d614610628578063abbb9f4c1461063b578063ad129e771461065057600080fd5b80639010d07c146105d357806391d14854146105e65780639c617c7e146105f957600080fd5b80637b0e1c5714610577578063811400fa1461058a57806381d69bba1461059d57806384b78414146105a55780638c6f4ab7146105b85780638f8eb812146105ca57600080fd5b8063445df08b11610277578063531acc13116102305780636269ff8f1161020a5780636269ff8f1461053057806369d3605c146105535780636eefea491461055b57806376ce2dad1461056e57600080fd5b8063531acc13146104f157806355358afb146104fa5780635c0478d11461050d57600080fd5b8063445df08b1461046f57806348c6ca77146104825780634ef1ccd1146104955780634f23c343146104a85780635010af4d146104bb57806350aaef5a146104ce57600080fd5b8063246b3502116102e45780632d50bb74116102be5780632d50bb74146104235780632f2ff15d146104365780633483369d1461044957806336568abe1461045c57600080fd5b8063246b3502146103e4578063248a9ca3146103f75780632542dbfd1461041b57600080fd5b806301ffc9a71461032c5780630250f9fe1461035457806303cad6451461035e57806305ac4e0b146103895780630e16f0c81461039c57806323991e4b146103d1575b600080fd5b61033f61033a366004612bd4565b610794565b60405190151581526020015b60405180910390f35b61035c6107bf565b005b600354610371906001600160a01b031681565b6040516001600160a01b03909116815260200161034b565b61035c610397366004612c1a565b61080f565b6103c37f507caaa5b2a5a027bc340a5334d9220583b7d60d846ee2aabc76e37d69a7253b81565b60405190815260200161034b565b61035c6103df366004612c1a565b610872565b61035c6103f2366004612c43565b61096b565b6103c3610405366004612c7a565b6000908152600160208190526040909120015490565b61035c610a00565b61035c610431366004612c1a565b610a52565b61035c610444366004612c93565b610ab8565b61035c610457366004612c1a565b610adf565b61035c61046a366004612c93565b610b48565b6103c361047d366004612cd5565b610bcb565b61035c610490366004612c1a565b611145565b61035c6104a3366004612c7a565b6111a8565b600654610371906001600160a01b031681565b600f54610371906001600160a01b031681565b61033f6104dc366004612c7a565b60046020526000908152604090205460ff1681565b6103c360075481565b600e54610371906001600160a01b031681565b61033f61051b366004612c1a565b60106020526000908152604090205460ff1681565b61033f61053e366004612c1a565b600a6020526000908152604090205460ff1681565b61035c6111f6565b6103c3610569366004612cd5565b61124a565b6103c360055481565b61035c610585366004612dbb565b6117f2565b600d54610371906001600160a01b031681565b61035c611818565b61035c6105b3366004612c1a565b611867565b60095461033f90610100900460ff1681565b6103c360085481565b6103716105e1366004612df7565b6118f7565b61033f6105f4366004612c93565b611916565b6103c37f023d9737d781c665e5048e4dfd034f07fec540e8ecb2336b3d85a375b90a3a3581565b6103c3600081565b61035c610636366004612c7a565b611941565b6103c360008051602061318783398151915281565b61035c61065e366004612c1a565b61198f565b61033f610671366004612c1a565b600b6020526000908152604090205460ff1681565b6103717f000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f181565b600c54610371906001600160a01b031681565b6103c3670de0b6b3a764000081565b61035c6106dd366004612c1a565b611a1f565b6103c36106f0366004612c7a565b611a85565b61035c610703366004612c93565b611a9c565b6103c36000805160206131c783398151915281565b60095461033f9060ff1681565b61035c610738366004612c1a565b611ac3565b6103c3611b53565b61035c610753366004612e19565b611b62565b6103c37faa6d9093095fdf69cb4e18b3e4053e238ec6e2d5a083964634b640da3b8f44a481565b6103c36000805160206131a783398151915281565b60006001600160e01b03198216635a05180f60e01b14806107b957506107b982611e04565b92915050565b6000805160206131a78339815191526107d88133611e39565b6009805461ff00191690556040517f8cba7e15b16021395abffdc05ba74a88afd2b3dce03e075ddb041760a389068890600090a150565b6000805160206131a78339815191526108288133611e39565b6001600160a01b0382166000818152600b6020526040808220805460ff19169055517ff7db4b816293b43fac22e1773acf5d3774a3d70ab993f04995406fadd92b546a9190a25050565b600061087e8133611e39565b6001600160a01b0382166108a557604051633d04535360e21b815260040160405180910390fd5b600c546040516001600160a01b038085169216907ff78e014ab86d7bb38135262d64726cef2e151dae47c0947a1d6bb970702c30d690600090a3600c80546001600160a01b0319166001600160a01b03848116918217909255600354604051637f19077160e01b81529216600483015230602483015290637f19077190604401602060405180830381865afa158015610942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109669190612e5b565b505050565b6000805160206131878339815191526109848133611e39565b6001600160a01b0383166109ab5760405163885ce5f160e01b815260040160405180910390fd5b6001600160a01b038316600081815260106020526040808220805460ff191686151590811790915590519092917f8f1a189329487ea2f651b3797ac87d45216b42a18c01a7335169539b76df133891a3505050565b6000805160206131c7833981519152610a198133611e39565b6009805460ff191660011790556040517f94eae7ff948a5ddfb0e5f291aa214ae9dd7d12ea33086a414143bc4a3408734190600090a150565b6000805160206131c7833981519152610a6b8133611e39565b6001600160a01b0382166000818152600b6020526040808220805460ff19166001179055517fcacc4dbd81af0cceec871b59f5155fa60dc3a52b970778ba54b2cf66f0b5deeb9190a25050565b60008281526001602081905260409091200154610ad58133611e39565b6109668383611e9d565b6000610aeb8133611e39565b6006546040516001600160a01b038085169216907fad45eab3ddda99c8b095504a58e25095a54c31dc487bb3eed9c0a9112ee4eaa890600090a350600680546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381163314610bbd5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b610bc78282611ebf565b5050565b6000600260005403610c1f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b6002600055610c346080860160608701612c1a565b60095460ff1615610c58576040516331852b7360e21b815260040160405180910390fd5b6001600160a01b0381166000908152600a602052604090205460ff1615610c915760405162e4b17560e11b815260040160405180910390fd5b6001600160a01b038416610cb85760405163885ce5f160e01b815260040160405180910390fd5b6000610ccb610100880160e08901612e8a565b6001811115610cdc57610cdc612e74565b14610cfa576040516326b1c87960e21b815260040160405180910390fd5b600c546003546000916001600160a01b0390811691637f1907719116336040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa158015610d62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d869190612e5b565b905080610da657604051632163950f60e01b815260040160405180910390fd5b610db1878783611ee1565b6020808801356000908152600490915260408120805460ff19166001179055670de0b6b3a7640000610deb60808a013560a08b0135612ec1565b610df59190612ee0565b9050600754811015610e1a576040516367627d0760e01b815260040160405180910390fd5b600d546001600160a01b0316637d4945b76000610e3d60808c0160608d01612c1a565b85856040518563ffffffff1660e01b8152600401610e5e9493929190612f20565b600060405180830381600087803b158015610e7857600080fd5b505af1158015610e8c573d6000803e3d6000fd5b505050507f000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f16001600160a01b0316866001600160a01b031603610f0357610efe7f000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f16001600160a01b03163330846121cb565b611029565b6006546001600160a01b0316610f2c5760405163cdce50bd60e01b815260040160405180910390fd5b610f416001600160a01b0387163330886121cb565b600654610f5b906001600160a01b03888116911687612232565b6006546040516322d4a17560e01b81526001600160a01b038881166004830152602482018890526044820184905260009216906322d4a175906064016020604051808303816000875af1158015610fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fda9190612e5b565b90506000610fe88383612f52565b9050801561102657611026335b6001600160a01b037f000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f11690836122c2565b50505b604051630852cd8d60e31b8152600481018290527f000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f16001600160a01b0316906342966c6890602401600060405180830381600087803b15801561108b57600080fd5b505af115801561109f573d6000803e3d6000fd5b506110b4925050506080890160608a01612c1a565b6001600160a01b03166340c10f19336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260a08b01356024820152604401600060405180830381600087803b15801561110e57600080fd5b505af1158015611122573d6000803e3d6000fd5b5050505061112f886122f3565b5050600160005550505060a09092013592915050565b6000805160206131a783398151915261115e8133611e39565b6001600160a01b0382166000818152600a6020526040808220805460ff19169055517f8ea8fa511d23c1a22f92d6480c103dff2994b522f89b46b18c9493130d1121de9190a25050565b6000805160206131878339815191526111c18133611e39565b6008546040518391907ffdaf6ed728cef208e62328a008209556f8281f3062b14dd08aaaa90fa159421190600090a350600855565b6000805160206131c783398151915261120f8133611e39565b6009805461ff0019166101001790556040517f694abd7c120a829fef1aac704885e405362fcd69c82f114ccec2959a402633c590600090a150565b600060026000540361129e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b60026000556112b36080860160608701612c1a565b600954610100900460ff16156112dc576040516378b17b4360e11b815260040160405180910390fd5b6001600160a01b0381166000908152600b602052604090205460ff16156113165760405163877009f360e01b815260040160405180910390fd5b6001600160a01b03841661133d5760405163885ce5f160e01b815260040160405180910390fd5b6001611350610100880160e08901612e8a565b600181111561136157611361612e74565b1461137f576040516326b1c87960e21b815260040160405180910390fd5b600c546003546000916001600160a01b0390811691637f1907719116336040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa1580156113e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140b9190612e5b565b90508061142b57604051632163950f60e01b815260040160405180910390fd5b611436878783611ee1565b6020808801356000908152600490915260409020805460ff1916600117905561148661145f3390565b3060a08a013561147560808c0160608d01612c1a565b6001600160a01b03169291906121cb565b6114966080880160608901612c1a565b604051630852cd8d60e31b815260a089013560048201526001600160a01b0391909116906342966c6890602401600060405180830381600087803b1580156114dd57600080fd5b505af11580156114f1573d6000803e3d6000fd5b505050506000670de0b6b3a764000088608001358960a001356115149190612ec1565b61151e9190612ee0565b90506008548110156115435760405163680116dd60e11b815260040160405180910390fd5b600d546001600160a01b0316637d4945b7600161156660808c0160608d01612c1a565b85856040518563ffffffff1660e01b81526004016115879493929190612f20565b600060405180830381600087803b1580156115a157600080fd5b505af11580156115b5573d6000803e3d6000fd5b50506040516340c10f1960e01b8152306004820152602481018490527f000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f16001600160a01b031692506340c10f199150604401600060405180830381600087803b15801561162157600080fd5b505af1158015611635573d6000803e3d6000fd5b505050507f000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f16001600160a01b0316866001600160a01b0316036116805761167b33610ff5565b6117d9565b6006546001600160a01b03166116a95760405163cdce50bd60e01b815260040160405180910390fd5b60065460405163095ea7b360e01b81526001600160a01b039182166004820152602481018390527f000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f19091169063095ea7b3906044016020604051808303816000875af115801561171d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117419190612f65565b5060065460405163d878016160e01b8152600481018390526001600160a01b03888116602483015260448201889052600092169063d8780161906064016020604051808303816000875af115801561179d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c19190612e5b565b90506117d76001600160a01b03881633836122c2565b505b6117e2886122f3565b6001600055979650505050505050565b60006117fe8133611e39565b6118126001600160a01b03851684846122c2565b50505050565b6000805160206131a78339815191526118318133611e39565b6009805460ff191690556040517f7c5bd2c6bf55553fb8379a172f2f9d0369fc18a7bf82a47486ac611a9215060190600090a150565b60006118738133611e39565b6001600160a01b03821661189a576040516301acb6d760e01b815260040160405180910390fd5b600f546040516001600160a01b038085169216907f7c40bb6767b8c6caf208ae3b9558c37a91b5710f5157deb182aae429ac24d33690600090a350600f80546001600160a01b0319166001600160a01b0392909216919091179055565b600082815260026020526040812061190f908361238b565b9392505050565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60008051602061318783398151915261195a8133611e39565b6007546040518391907fe6e25add7363f8f8a40cbea9810d3115a33703b10972ef759104219b0065743690600090a350600755565b600061199b8133611e39565b6001600160a01b0382166119c257604051633aa9ba3360e01b815260040160405180910390fd5b600d546040516001600160a01b038085169216907fc54bf4c3067c1d8f65e053dafb5dbb699615b1b527d2866bd0223102bb2e692d90600090a350600d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000805160206131c7833981519152611a388133611e39565b6001600160a01b0382166000818152600a6020526040808220805460ff19166001179055517f0de7e27328f4d5d9fc5797bf8cc1f3ca9c0d366a83aae68215e9e7dbf156a1f19190a25050565b60008181526002602052604081206107b990612397565b60008281526001602081905260409091200154611ab98133611e39565b6109668383611ebf565b6000611acf8133611e39565b6001600160a01b038216611af657604051630e1164bf60e21b815260040160405180910390fd5b600e546040516001600160a01b038085169216907fcaf02d44223f855a96856532b7f6b262b8c1e57639d6ea29ff00f49b65d6a0be90600090a350600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000611b5d6123a1565b905090565b600954849060ff1615611b88576040516331852b7360e21b815260040160405180910390fd5b6001600160a01b0381166000908152600a602052604090205460ff1615611bc15760405162e4b17560e11b815260040160405180910390fd5b7f507caaa5b2a5a027bc340a5334d9220583b7d60d846ee2aabc76e37d69a7253b611bec8133611e39565b6001600160a01b03861660009081526010602052604090205460ff16611c25576040516326b5ecf360e01b815260040160405180910390fd5b600c54600354604051637f19077160e01b81526001600160a01b03918216600482015287821660248201526000929190911690637f19077190604401602060405180830381865afa158015611c7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca29190612e5b565b905080611cc257604051632163950f60e01b815260040160405180910390fd5b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528816906340c10f1990604401600060405180830381600087803b158015611d0c57600080fd5b505af1158015611d20573d6000803e3d6000fd5b50505050866001600160a01b031681876001600160a01b03167f64246d088e96d6b1bbb49bd2ab458376867796a99add0e25a88c53bcee7ddbdf8888604051611d73929190918252602082015260400190565b60405180910390a450505050505050565b611d8e8282611916565b610bc75760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b600061190f836001600160a01b0384166124c8565b60006001600160e01b03198216637965db0b60e01b14806107b957506301ffc9a760e01b6001600160e01b03198316146107b9565b611e438282611916565b610bc757611e5b816001600160a01b03166014612517565b611e66836020612517565b604051602001611e77929190612fa6565b60408051601f198184030181529082905262461bcd60e51b8252610bb49160040161301b565b611ea78282611d84565b60008281526002602052604090206109669082611def565b611ec982826126b3565b6000828152600260205260409020610966908261271a565b60208084013560009081526004909152604090205460ff1615611f17576040516308d0ea5b60e31b815260040160405180910390fd5b8260c00135421115611f3c5760405163716dcc3960e01b815260040160405180910390fd5b82604001358114611f6d576040805163748b3dc360e11b815260048101839052908401356024820152604401610bb4565b600e60009054906101000a90046001600160a01b03166001600160a01b031663e8c7e7286040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611fbd57600080fd5b505af1158015611fd1573d6000803e3d6000fd5b5050600f546001600160a01b0316915063fd45a4339050611ff86080860160608701612c1a565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526080860135602482015260440160006040518083038186803b15801561204157600080fd5b505afa158015612055573d6000803e3d6000fd5b50505050601060008460600160208101906120709190612c1a565b6001600160a01b03168152602081019190915260400160009081205460ff16151590036120b0576040516326b5ecf360e01b815260040160405180910390fd5b823546146120d157604051633d23e4d160e11b815260040160405180910390fd5b600061216d7faa6d9093095fdf69cb4e18b3e4053e238ec6e2d5a083964634b640da3b8f44a485356020870135604088013561211360808a0160608b01612c1a565b60808a013560a08b013560c08c01356121336101008e0160e08f01612e8a565b8d61010001356040516020016121529a9998979695949392919061304e565b6040516020818303038152906040528051906020012061272f565b9050600061217b828561277d565b90506121a77f023d9737d781c665e5048e4dfd034f07fec540e8ecb2336b3d85a375b90a3a3582611916565b6121c45760405163127a982d60e01b815260040160405180910390fd5b5050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526118129186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506127a1565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526122838482612812565b611812576040516001600160a01b038481166024830152600060448301526122b891869182169063095ea7b390606401612200565b61181284826127a1565b6040516001600160a01b0383811660248301526044820183905261096691859182169063a9059cbb90606401612200565b7fdfe4debbd7bc491e9db43820916e30a4ef9490863fc22b1e79e2f76013901035600560008154612323906130b2565b9182905550602083013583356040850135612345610100870160e08801612e8a565b6123556080880160608901612c1a565b87608001358860a001358960c001358a61010001356040516123809a999897969594939291906130cb565b60405180910390a150565b600061190f8383612861565b60006107b9825490565b6000306001600160a01b037f0000000000000000000000002c158bc456e027b2affccadf1bdbd9f5fc4c5c8c161480156123fa57507f000000000000000000000000000000000000000000000000000000000000000146145b1561242457507fe366cab15d2bf3f9f295fa4d4f299170e44e971d8e7f1808dfef3c453692222c90565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f95ed386835dc204e5cd2629625d0c3fb319cf204ef02efd869f16db3cc0f04ce828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b600081815260018301602052604081205461250f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107b9565b5060006107b9565b60606000612526836002612ec1565b612531906002613130565b67ffffffffffffffff81111561254957612549612cbf565b6040519080825280601f01601f191660200182016040528015612573576020820181803683370190505b509050600360fc1b8160008151811061258e5761258e613143565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106125bd576125bd613143565b60200101906001600160f81b031916908160001a90535060006125e1846002612ec1565b6125ec906001613130565b90505b6001811115612664576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061262057612620613143565b1a60f81b82828151811061263657612636613143565b60200101906001600160f81b031916908160001a90535060049490941c9361265d81613159565b90506125ef565b50831561190f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610bb4565b6126bd8282611916565b15610bc75760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600061190f836001600160a01b03841661288b565b60006107b961273c6123a1565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600080600061278c858561297e565b91509150612799816129c3565b509392505050565b600080602060008451602086016000885af1806127c4576040513d6000823e3d81fd5b50506000513d915081156127dc5780600114156127e9565b6001600160a01b0384163b155b1561181257604051635274afe760e01b81526001600160a01b0385166004820152602401610bb4565b6000806000806020600086516020880160008a5af192503d91506000519050828015612857575081156128485780600114612857565b6000866001600160a01b03163b115b9695505050505050565b600082600001828154811061287857612878613143565b9060005260206000200154905092915050565b600081815260018301602052604081205480156129745760006128af600183612f52565b85549091506000906128c390600190612f52565b90508181146129285760008660000182815481106128e3576128e3613143565b906000526020600020015490508087600001848154811061290657612906613143565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061293957612939613170565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107b9565b60009150506107b9565b60008082516041036129b45760208301516040840151606085015160001a6129a887828585612b10565b945094505050506129bc565b506000905060025b9250929050565b60008160048111156129d7576129d7612e74565b036129df5750565b60018160048111156129f3576129f3612e74565b03612a405760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610bb4565b6002816004811115612a5457612a54612e74565b03612aa15760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610bb4565b6003816004811115612ab557612ab5612e74565b03612b0d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610bb4565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612b475750600090506003612bcb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612b9b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612bc457600060019250925050612bcb565b9150600090505b94509492505050565b600060208284031215612be657600080fd5b81356001600160e01b03198116811461190f57600080fd5b80356001600160a01b0381168114612c1557600080fd5b919050565b600060208284031215612c2c57600080fd5b61190f82612bfe565b8015158114612b0d57600080fd5b60008060408385031215612c5657600080fd5b612c5f83612bfe565b91506020830135612c6f81612c35565b809150509250929050565b600060208284031215612c8c57600080fd5b5035919050565b60008060408385031215612ca657600080fd5b82359150612cb660208401612bfe565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600080600080848603610180811215612ced57600080fd5b61012080821215612cfd57600080fd5b869550850135905067ffffffffffffffff80821115612d1b57600080fd5b818701915087601f830112612d2f57600080fd5b813581811115612d4157612d41612cbf565b604051601f8201601f19908116603f01168101908382118183101715612d6957612d69612cbf565b816040528281528a6020848701011115612d8257600080fd5b826020860160208301376000602084830101528097505050505050612daa6101408601612bfe565b939692955092936101600135925050565b600080600060608486031215612dd057600080fd5b612dd984612bfe565b9250612de760208501612bfe565b9150604084013590509250925092565b60008060408385031215612e0a57600080fd5b50508035926020909101359150565b60008060008060808587031215612e2f57600080fd5b612e3885612bfe565b9350612e4660208601612bfe565b93969395505050506040820135916060013590565b600060208284031215612e6d57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b600060208284031215612e9c57600080fd5b81356002811061190f57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615612edb57612edb612eab565b500290565b600082612efd57634e487b7160e01b600052601260045260246000fd5b500490565b60028110612b0d57634e487b7160e01b600052602160045260246000fd5b60808101612f2d86612f02565b9481526001600160a01b03939093166020840152604083019190915260609091015290565b818103818111156107b9576107b9612eab565b600060208284031215612f7757600080fd5b815161190f81612c35565b60005b83811015612f9d578181015183820152602001612f85565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612fde816017850160208801612f82565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161300f816028840160208801612f82565b01602801949350505050565b602081526000825180602084015261303a816040850160208701612f82565b601f01601f19169190910160400192915050565b8a8152602081018a905260408101899052606081018890526001600160a01b038716608082015260a0810186905260c0810185905260e08101849052610140810161309884612f02565b610100820193909352610120015298975050505050505050565b6000600182016130c4576130c4612eab565b5060010190565b6000610140820190508b82528a60208301528960408301528860608301526130f288612f02565b60808201979097526001600160a01b039590951660a086015260c085019390935260e084019190915261010083015261012090910152949350505050565b808201808211156107b9576107b9612eab565b634e487b7160e01b600052603260045260246000fd5b60008161316857613168612eab565b506000190190565b634e487b7160e01b600052603160045260246000fdfef45c97b23e2beeefda80e1ce5cb3e234aa7b6888ad5cbabb75bfd654dd8e102d427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862aa2646970667358221220e211d9dde0d4ad5835acdb86363cbd2b4d1eb9b33248d0affbd6f834922125e364736f6c63430008100033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"london","libraries":{},"metadata":{"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":200},"remappings":["eth-gas-reporter/=node_modules/eth-gas-reporter/","forge-tests/=forge-tests/","lib/=lib/","@aragon/=node_modules/@aragon/","@ensdomains/=node_modules/@ensdomains/","@openzeppelin/=node_modules/@openzeppelin/","@uniswap/=node_modules/@uniswap/","forge-std/=lib/forge-std/src/","hardhat-deploy/=node_modules/hardhat-deploy/","hardhat/=node_modules/hardhat/","math/=node_modules/@aragon/os/contracts/lib/math/","misc/=node_modules/@aragon/os/contracts/lib/misc/","solidity-bytes-utils/=node_modules/solidity-bytes-utils/","standards/=node_modules/@aragon/os/contracts/lib/standards/","token/=node_modules/@aragon/os/contracts/lib/token/","truffle/=node_modules/truffle/"],"viaIR":false},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":[["0x54b5Aae5bdA007DB744Ea762460A96F24BC1F4ad",{"internalType":"address","name":"_defaultAdmin","type":"address"}],["0xAcE8E719899F6E91831B18AE746C9A965c2119F1",{"internalType":"address","name":"_usdon","type":"address"}],["1000000000000000000",{"internalType":"uint256","name":"_minimumDepositUSD","type":"uint256"}],["1000000000000000000",{"internalType":"uint256","name":"_minimumRedemptionUSD","type":"uint256"}]],"compiler_version":"0.8.16+commit.07a7930e","is_verified_via_verifier_alliance":true,"verified_at":"2025-08-11T17:41:37.904013Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6d676c6f62616c5f6d61726b65747360901b61018052600e6101605261018e604052600380546001600160a01b03191673428ecb70e90d1527a5f5e177789f51747b883f3417905560006005553480156200005957600080fd5b506040516200361a3803806200361a8339810160408190526200007c916200032a565b604080518082018252601281527127b73237a3a6aa37b5b2b726b0b730b3b2b960711b6020808301918252835180850190945260018452603160f81b908401528151902060e08190527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66101008190524660a0529192917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620001648184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6080523060c052610120525050600160005550506001600160a01b038316620001a057604051632f5edb4360e11b815260040160405180910390fd5b6001600160a01b0383166101405260078290556008819055620001c5600085620001cf565b5050505062000372565b620001e682826200021260201b62001d841760201c565b60008281526002602090815260409091206200020d91839062001def6200029b821b17901c565b505050565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff16620002975760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45b5050565b6000620002b2836001600160a01b038416620002bb565b90505b92915050565b60008181526001830160205260408120546200030457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620002b5565b506000620002b5565b80516001600160a01b03811681146200032557600080fd5b919050565b600080600080608085870312156200034157600080fd5b6200034c856200030d565b93506200035c602086016200030d565b6040860151606090960151949790965092505050565b60805160a05160c05160e05161010051610120516101405161321c620003fe6000396000818161068b01528181610e9201528181610ece01528181610fff0152818161103f015281816115d30152818161163b01526116d20152600061242b0152600061247a01526000612455015260006123ae015260006123d801526000612402015261321c6000f3fe608060405234801561001057600080fd5b50600436106103275760003560e01c80637b0e1c57116101b8578063b28996b511610104578063e63ab1e9116100a2578063ed24911d1161007c578063ed24911d1461073d578063ed2a354014610745578063f758161514610758578063fb1bb9de1461077f57600080fd5b8063e63ab1e914610708578063eb27fa531461071d578063ebaf3f211461072a57600080fd5b8063c7f8e171116100de578063c7f8e171146106c0578063c875edf6146106cf578063ca15c873146106e2578063d547741f146106f557600080fd5b8063b28996b514610663578063bd5d370c14610686578063c768b145146106ad57600080fd5b80639010d07c11610171578063a217fddf1161014b578063a217fddf14610620578063aab483d614610628578063abbb9f4c1461063b578063ad129e771461065057600080fd5b80639010d07c146105d357806391d14854146105e65780639c617c7e146105f957600080fd5b80637b0e1c5714610577578063811400fa1461058a57806381d69bba1461059d57806384b78414146105a55780638c6f4ab7146105b85780638f8eb812146105ca57600080fd5b8063445df08b11610277578063531acc13116102305780636269ff8f1161020a5780636269ff8f1461053057806369d3605c146105535780636eefea491461055b57806376ce2dad1461056e57600080fd5b8063531acc13146104f157806355358afb146104fa5780635c0478d11461050d57600080fd5b8063445df08b1461046f57806348c6ca77146104825780634ef1ccd1146104955780634f23c343146104a85780635010af4d146104bb57806350aaef5a146104ce57600080fd5b8063246b3502116102e45780632d50bb74116102be5780632d50bb74146104235780632f2ff15d146104365780633483369d1461044957806336568abe1461045c57600080fd5b8063246b3502146103e4578063248a9ca3146103f75780632542dbfd1461041b57600080fd5b806301ffc9a71461032c5780630250f9fe1461035457806303cad6451461035e57806305ac4e0b146103895780630e16f0c81461039c57806323991e4b146103d1575b600080fd5b61033f61033a366004612bd4565b610794565b60405190151581526020015b60405180910390f35b61035c6107bf565b005b600354610371906001600160a01b031681565b6040516001600160a01b03909116815260200161034b565b61035c610397366004612c1a565b61080f565b6103c37f507caaa5b2a5a027bc340a5334d9220583b7d60d846ee2aabc76e37d69a7253b81565b60405190815260200161034b565b61035c6103df366004612c1a565b610872565b61035c6103f2366004612c43565b61096b565b6103c3610405366004612c7a565b6000908152600160208190526040909120015490565b61035c610a00565b61035c610431366004612c1a565b610a52565b61035c610444366004612c93565b610ab8565b61035c610457366004612c1a565b610adf565b61035c61046a366004612c93565b610b48565b6103c361047d366004612cd5565b610bcb565b61035c610490366004612c1a565b611145565b61035c6104a3366004612c7a565b6111a8565b600654610371906001600160a01b031681565b600f54610371906001600160a01b031681565b61033f6104dc366004612c7a565b60046020526000908152604090205460ff1681565b6103c360075481565b600e54610371906001600160a01b031681565b61033f61051b366004612c1a565b60106020526000908152604090205460ff1681565b61033f61053e366004612c1a565b600a6020526000908152604090205460ff1681565b61035c6111f6565b6103c3610569366004612cd5565b61124a565b6103c360055481565b61035c610585366004612dbb565b6117f2565b600d54610371906001600160a01b031681565b61035c611818565b61035c6105b3366004612c1a565b611867565b60095461033f90610100900460ff1681565b6103c360085481565b6103716105e1366004612df7565b6118f7565b61033f6105f4366004612c93565b611916565b6103c37f023d9737d781c665e5048e4dfd034f07fec540e8ecb2336b3d85a375b90a3a3581565b6103c3600081565b61035c610636366004612c7a565b611941565b6103c360008051602061318783398151915281565b61035c61065e366004612c1a565b61198f565b61033f610671366004612c1a565b600b6020526000908152604090205460ff1681565b6103717f000000000000000000000000000000000000000000000000000000000000000081565b600c54610371906001600160a01b031681565b6103c3670de0b6b3a764000081565b61035c6106dd366004612c1a565b611a1f565b6103c36106f0366004612c7a565b611a85565b61035c610703366004612c93565b611a9c565b6103c36000805160206131c783398151915281565b60095461033f9060ff1681565b61035c610738366004612c1a565b611ac3565b6103c3611b53565b61035c610753366004612e19565b611b62565b6103c37faa6d9093095fdf69cb4e18b3e4053e238ec6e2d5a083964634b640da3b8f44a481565b6103c36000805160206131a783398151915281565b60006001600160e01b03198216635a05180f60e01b14806107b957506107b982611e04565b92915050565b6000805160206131a78339815191526107d88133611e39565b6009805461ff00191690556040517f8cba7e15b16021395abffdc05ba74a88afd2b3dce03e075ddb041760a389068890600090a150565b6000805160206131a78339815191526108288133611e39565b6001600160a01b0382166000818152600b6020526040808220805460ff19169055517ff7db4b816293b43fac22e1773acf5d3774a3d70ab993f04995406fadd92b546a9190a25050565b600061087e8133611e39565b6001600160a01b0382166108a557604051633d04535360e21b815260040160405180910390fd5b600c546040516001600160a01b038085169216907ff78e014ab86d7bb38135262d64726cef2e151dae47c0947a1d6bb970702c30d690600090a3600c80546001600160a01b0319166001600160a01b03848116918217909255600354604051637f19077160e01b81529216600483015230602483015290637f19077190604401602060405180830381865afa158015610942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109669190612e5b565b505050565b6000805160206131878339815191526109848133611e39565b6001600160a01b0383166109ab5760405163885ce5f160e01b815260040160405180910390fd5b6001600160a01b038316600081815260106020526040808220805460ff191686151590811790915590519092917f8f1a189329487ea2f651b3797ac87d45216b42a18c01a7335169539b76df133891a3505050565b6000805160206131c7833981519152610a198133611e39565b6009805460ff191660011790556040517f94eae7ff948a5ddfb0e5f291aa214ae9dd7d12ea33086a414143bc4a3408734190600090a150565b6000805160206131c7833981519152610a6b8133611e39565b6001600160a01b0382166000818152600b6020526040808220805460ff19166001179055517fcacc4dbd81af0cceec871b59f5155fa60dc3a52b970778ba54b2cf66f0b5deeb9190a25050565b60008281526001602081905260409091200154610ad58133611e39565b6109668383611e9d565b6000610aeb8133611e39565b6006546040516001600160a01b038085169216907fad45eab3ddda99c8b095504a58e25095a54c31dc487bb3eed9c0a9112ee4eaa890600090a350600680546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381163314610bbd5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b610bc78282611ebf565b5050565b6000600260005403610c1f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b6002600055610c346080860160608701612c1a565b60095460ff1615610c58576040516331852b7360e21b815260040160405180910390fd5b6001600160a01b0381166000908152600a602052604090205460ff1615610c915760405162e4b17560e11b815260040160405180910390fd5b6001600160a01b038416610cb85760405163885ce5f160e01b815260040160405180910390fd5b6000610ccb610100880160e08901612e8a565b6001811115610cdc57610cdc612e74565b14610cfa576040516326b1c87960e21b815260040160405180910390fd5b600c546003546000916001600160a01b0390811691637f1907719116336040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa158015610d62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d869190612e5b565b905080610da657604051632163950f60e01b815260040160405180910390fd5b610db1878783611ee1565b6020808801356000908152600490915260408120805460ff19166001179055670de0b6b3a7640000610deb60808a013560a08b0135612ec1565b610df59190612ee0565b9050600754811015610e1a576040516367627d0760e01b815260040160405180910390fd5b600d546001600160a01b0316637d4945b76000610e3d60808c0160608d01612c1a565b85856040518563ffffffff1660e01b8152600401610e5e9493929190612f20565b600060405180830381600087803b158015610e7857600080fd5b505af1158015610e8c573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031603610f0357610efe7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163330846121cb565b611029565b6006546001600160a01b0316610f2c5760405163cdce50bd60e01b815260040160405180910390fd5b610f416001600160a01b0387163330886121cb565b600654610f5b906001600160a01b03888116911687612232565b6006546040516322d4a17560e01b81526001600160a01b038881166004830152602482018890526044820184905260009216906322d4a175906064016020604051808303816000875af1158015610fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fda9190612e5b565b90506000610fe88383612f52565b9050801561102657611026335b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690836122c2565b50505b604051630852cd8d60e31b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c6890602401600060405180830381600087803b15801561108b57600080fd5b505af115801561109f573d6000803e3d6000fd5b506110b4925050506080890160608a01612c1a565b6001600160a01b03166340c10f19336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260a08b01356024820152604401600060405180830381600087803b15801561110e57600080fd5b505af1158015611122573d6000803e3d6000fd5b5050505061112f886122f3565b5050600160005550505060a09092013592915050565b6000805160206131a783398151915261115e8133611e39565b6001600160a01b0382166000818152600a6020526040808220805460ff19169055517f8ea8fa511d23c1a22f92d6480c103dff2994b522f89b46b18c9493130d1121de9190a25050565b6000805160206131878339815191526111c18133611e39565b6008546040518391907ffdaf6ed728cef208e62328a008209556f8281f3062b14dd08aaaa90fa159421190600090a350600855565b6000805160206131c783398151915261120f8133611e39565b6009805461ff0019166101001790556040517f694abd7c120a829fef1aac704885e405362fcd69c82f114ccec2959a402633c590600090a150565b600060026000540361129e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bb4565b60026000556112b36080860160608701612c1a565b600954610100900460ff16156112dc576040516378b17b4360e11b815260040160405180910390fd5b6001600160a01b0381166000908152600b602052604090205460ff16156113165760405163877009f360e01b815260040160405180910390fd5b6001600160a01b03841661133d5760405163885ce5f160e01b815260040160405180910390fd5b6001611350610100880160e08901612e8a565b600181111561136157611361612e74565b1461137f576040516326b1c87960e21b815260040160405180910390fd5b600c546003546000916001600160a01b0390811691637f1907719116336040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa1580156113e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140b9190612e5b565b90508061142b57604051632163950f60e01b815260040160405180910390fd5b611436878783611ee1565b6020808801356000908152600490915260409020805460ff1916600117905561148661145f3390565b3060a08a013561147560808c0160608d01612c1a565b6001600160a01b03169291906121cb565b6114966080880160608901612c1a565b604051630852cd8d60e31b815260a089013560048201526001600160a01b0391909116906342966c6890602401600060405180830381600087803b1580156114dd57600080fd5b505af11580156114f1573d6000803e3d6000fd5b505050506000670de0b6b3a764000088608001358960a001356115149190612ec1565b61151e9190612ee0565b90506008548110156115435760405163680116dd60e11b815260040160405180910390fd5b600d546001600160a01b0316637d4945b7600161156660808c0160608d01612c1a565b85856040518563ffffffff1660e01b81526004016115879493929190612f20565b600060405180830381600087803b1580156115a157600080fd5b505af11580156115b5573d6000803e3d6000fd5b50506040516340c10f1960e01b8152306004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692506340c10f199150604401600060405180830381600087803b15801561162157600080fd5b505af1158015611635573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b0316036116805761167b33610ff5565b6117d9565b6006546001600160a01b03166116a95760405163cdce50bd60e01b815260040160405180910390fd5b60065460405163095ea7b360e01b81526001600160a01b039182166004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af115801561171d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117419190612f65565b5060065460405163d878016160e01b8152600481018390526001600160a01b03888116602483015260448201889052600092169063d8780161906064016020604051808303816000875af115801561179d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c19190612e5b565b90506117d76001600160a01b03881633836122c2565b505b6117e2886122f3565b6001600055979650505050505050565b60006117fe8133611e39565b6118126001600160a01b03851684846122c2565b50505050565b6000805160206131a78339815191526118318133611e39565b6009805460ff191690556040517f7c5bd2c6bf55553fb8379a172f2f9d0369fc18a7bf82a47486ac611a9215060190600090a150565b60006118738133611e39565b6001600160a01b03821661189a576040516301acb6d760e01b815260040160405180910390fd5b600f546040516001600160a01b038085169216907f7c40bb6767b8c6caf208ae3b9558c37a91b5710f5157deb182aae429ac24d33690600090a350600f80546001600160a01b0319166001600160a01b0392909216919091179055565b600082815260026020526040812061190f908361238b565b9392505050565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60008051602061318783398151915261195a8133611e39565b6007546040518391907fe6e25add7363f8f8a40cbea9810d3115a33703b10972ef759104219b0065743690600090a350600755565b600061199b8133611e39565b6001600160a01b0382166119c257604051633aa9ba3360e01b815260040160405180910390fd5b600d546040516001600160a01b038085169216907fc54bf4c3067c1d8f65e053dafb5dbb699615b1b527d2866bd0223102bb2e692d90600090a350600d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000805160206131c7833981519152611a388133611e39565b6001600160a01b0382166000818152600a6020526040808220805460ff19166001179055517f0de7e27328f4d5d9fc5797bf8cc1f3ca9c0d366a83aae68215e9e7dbf156a1f19190a25050565b60008181526002602052604081206107b990612397565b60008281526001602081905260409091200154611ab98133611e39565b6109668383611ebf565b6000611acf8133611e39565b6001600160a01b038216611af657604051630e1164bf60e21b815260040160405180910390fd5b600e546040516001600160a01b038085169216907fcaf02d44223f855a96856532b7f6b262b8c1e57639d6ea29ff00f49b65d6a0be90600090a350600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000611b5d6123a1565b905090565b600954849060ff1615611b88576040516331852b7360e21b815260040160405180910390fd5b6001600160a01b0381166000908152600a602052604090205460ff1615611bc15760405162e4b17560e11b815260040160405180910390fd5b7f507caaa5b2a5a027bc340a5334d9220583b7d60d846ee2aabc76e37d69a7253b611bec8133611e39565b6001600160a01b03861660009081526010602052604090205460ff16611c25576040516326b5ecf360e01b815260040160405180910390fd5b600c54600354604051637f19077160e01b81526001600160a01b03918216600482015287821660248201526000929190911690637f19077190604401602060405180830381865afa158015611c7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca29190612e5b565b905080611cc257604051632163950f60e01b815260040160405180910390fd5b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528816906340c10f1990604401600060405180830381600087803b158015611d0c57600080fd5b505af1158015611d20573d6000803e3d6000fd5b50505050866001600160a01b031681876001600160a01b03167f64246d088e96d6b1bbb49bd2ab458376867796a99add0e25a88c53bcee7ddbdf8888604051611d73929190918252602082015260400190565b60405180910390a450505050505050565b611d8e8282611916565b610bc75760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b600061190f836001600160a01b0384166124c8565b60006001600160e01b03198216637965db0b60e01b14806107b957506301ffc9a760e01b6001600160e01b03198316146107b9565b611e438282611916565b610bc757611e5b816001600160a01b03166014612517565b611e66836020612517565b604051602001611e77929190612fa6565b60408051601f198184030181529082905262461bcd60e51b8252610bb49160040161301b565b611ea78282611d84565b60008281526002602052604090206109669082611def565b611ec982826126b3565b6000828152600260205260409020610966908261271a565b60208084013560009081526004909152604090205460ff1615611f17576040516308d0ea5b60e31b815260040160405180910390fd5b8260c00135421115611f3c5760405163716dcc3960e01b815260040160405180910390fd5b82604001358114611f6d576040805163748b3dc360e11b815260048101839052908401356024820152604401610bb4565b600e60009054906101000a90046001600160a01b03166001600160a01b031663e8c7e7286040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611fbd57600080fd5b505af1158015611fd1573d6000803e3d6000fd5b5050600f546001600160a01b0316915063fd45a4339050611ff86080860160608701612c1a565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526080860135602482015260440160006040518083038186803b15801561204157600080fd5b505afa158015612055573d6000803e3d6000fd5b50505050601060008460600160208101906120709190612c1a565b6001600160a01b03168152602081019190915260400160009081205460ff16151590036120b0576040516326b5ecf360e01b815260040160405180910390fd5b823546146120d157604051633d23e4d160e11b815260040160405180910390fd5b600061216d7faa6d9093095fdf69cb4e18b3e4053e238ec6e2d5a083964634b640da3b8f44a485356020870135604088013561211360808a0160608b01612c1a565b60808a013560a08b013560c08c01356121336101008e0160e08f01612e8a565b8d61010001356040516020016121529a9998979695949392919061304e565b6040516020818303038152906040528051906020012061272f565b9050600061217b828561277d565b90506121a77f023d9737d781c665e5048e4dfd034f07fec540e8ecb2336b3d85a375b90a3a3582611916565b6121c45760405163127a982d60e01b815260040160405180910390fd5b5050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526118129186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506127a1565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526122838482612812565b611812576040516001600160a01b038481166024830152600060448301526122b891869182169063095ea7b390606401612200565b61181284826127a1565b6040516001600160a01b0383811660248301526044820183905261096691859182169063a9059cbb90606401612200565b7fdfe4debbd7bc491e9db43820916e30a4ef9490863fc22b1e79e2f76013901035600560008154612323906130b2565b9182905550602083013583356040850135612345610100870160e08801612e8a565b6123556080880160608901612c1a565b87608001358860a001358960c001358a61010001356040516123809a999897969594939291906130cb565b60405180910390a150565b600061190f8383612861565b60006107b9825490565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156123fa57507f000000000000000000000000000000000000000000000000000000000000000046145b1561242457507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b600081815260018301602052604081205461250f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107b9565b5060006107b9565b60606000612526836002612ec1565b612531906002613130565b67ffffffffffffffff81111561254957612549612cbf565b6040519080825280601f01601f191660200182016040528015612573576020820181803683370190505b509050600360fc1b8160008151811061258e5761258e613143565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106125bd576125bd613143565b60200101906001600160f81b031916908160001a90535060006125e1846002612ec1565b6125ec906001613130565b90505b6001811115612664576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061262057612620613143565b1a60f81b82828151811061263657612636613143565b60200101906001600160f81b031916908160001a90535060049490941c9361265d81613159565b90506125ef565b50831561190f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610bb4565b6126bd8282611916565b15610bc75760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600061190f836001600160a01b03841661288b565b60006107b961273c6123a1565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600080600061278c858561297e565b91509150612799816129c3565b509392505050565b600080602060008451602086016000885af1806127c4576040513d6000823e3d81fd5b50506000513d915081156127dc5780600114156127e9565b6001600160a01b0384163b155b1561181257604051635274afe760e01b81526001600160a01b0385166004820152602401610bb4565b6000806000806020600086516020880160008a5af192503d91506000519050828015612857575081156128485780600114612857565b6000866001600160a01b03163b115b9695505050505050565b600082600001828154811061287857612878613143565b9060005260206000200154905092915050565b600081815260018301602052604081205480156129745760006128af600183612f52565b85549091506000906128c390600190612f52565b90508181146129285760008660000182815481106128e3576128e3613143565b906000526020600020015490508087600001848154811061290657612906613143565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061293957612939613170565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107b9565b60009150506107b9565b60008082516041036129b45760208301516040840151606085015160001a6129a887828585612b10565b945094505050506129bc565b506000905060025b9250929050565b60008160048111156129d7576129d7612e74565b036129df5750565b60018160048111156129f3576129f3612e74565b03612a405760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610bb4565b6002816004811115612a5457612a54612e74565b03612aa15760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610bb4565b6003816004811115612ab557612ab5612e74565b03612b0d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610bb4565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612b475750600090506003612bcb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612b9b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612bc457600060019250925050612bcb565b9150600090505b94509492505050565b600060208284031215612be657600080fd5b81356001600160e01b03198116811461190f57600080fd5b80356001600160a01b0381168114612c1557600080fd5b919050565b600060208284031215612c2c57600080fd5b61190f82612bfe565b8015158114612b0d57600080fd5b60008060408385031215612c5657600080fd5b612c5f83612bfe565b91506020830135612c6f81612c35565b809150509250929050565b600060208284031215612c8c57600080fd5b5035919050565b60008060408385031215612ca657600080fd5b82359150612cb660208401612bfe565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600080600080848603610180811215612ced57600080fd5b61012080821215612cfd57600080fd5b869550850135905067ffffffffffffffff80821115612d1b57600080fd5b818701915087601f830112612d2f57600080fd5b813581811115612d4157612d41612cbf565b604051601f8201601f19908116603f01168101908382118183101715612d6957612d69612cbf565b816040528281528a6020848701011115612d8257600080fd5b826020860160208301376000602084830101528097505050505050612daa6101408601612bfe565b939692955092936101600135925050565b600080600060608486031215612dd057600080fd5b612dd984612bfe565b9250612de760208501612bfe565b9150604084013590509250925092565b60008060408385031215612e0a57600080fd5b50508035926020909101359150565b60008060008060808587031215612e2f57600080fd5b612e3885612bfe565b9350612e4660208601612bfe565b93969395505050506040820135916060013590565b600060208284031215612e6d57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b600060208284031215612e9c57600080fd5b81356002811061190f57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615612edb57612edb612eab565b500290565b600082612efd57634e487b7160e01b600052601260045260246000fd5b500490565b60028110612b0d57634e487b7160e01b600052602160045260246000fd5b60808101612f2d86612f02565b9481526001600160a01b03939093166020840152604083019190915260609091015290565b818103818111156107b9576107b9612eab565b600060208284031215612f7757600080fd5b815161190f81612c35565b60005b83811015612f9d578181015183820152602001612f85565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612fde816017850160208801612f82565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161300f816028840160208801612f82565b01602801949350505050565b602081526000825180602084015261303a816040850160208701612f82565b601f01601f19169190910160400192915050565b8a8152602081018a905260408101899052606081018890526001600160a01b038716608082015260a0810186905260c0810185905260e08101849052610140810161309884612f02565b610100820193909352610120015298975050505050505050565b6000600182016130c4576130c4612eab565b5060010190565b6000610140820190508b82528a60208301528960408301528860608301526130f288612f02565b60808201979097526001600160a01b039590951660a086015260c085019390935260e084019190915261010083015261012090910152949350505050565b808201808211156107b9576107b9612eab565b634e487b7160e01b600052603260045260246000fd5b60008161316857613168612eab565b506000190190565b634e487b7160e01b600052603160045260246000fdfef45c97b23e2beeefda80e1ce5cb3e234aa7b6888ad5cbabb75bfd654dd8e102d427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862aa2646970667358221220e211d9dde0d4ad5835acdb86363cbd2b4d1eb9b33248d0affbd6f834922125e364736f6c6343000810003300000000000000000000000054b5aae5bda007db744ea762460a96f24bc1f4ad000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f10000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a7640000","name":"GMTokenManager","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"london","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"contracts/external/openzeppelin/contracts/access/AccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/access/IAccessControl.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/Context.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/Strings.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n  struct RoleData {\n    mapping(address => bool) members;\n    bytes32 adminRole;\n  }\n\n  mapping(bytes32 => RoleData) private _roles;\n\n  bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n  /**\n   * @dev Modifier that checks that an account has a specific role. Reverts\n   * with a standardized message including the required role.\n   *\n   * The format of the revert reason is given by the following regular expression:\n   *\n   *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n   *\n   * _Available since v4.1._\n   */\n  modifier onlyRole(bytes32 role) {\n    _checkRole(role, _msgSender());\n    _;\n  }\n\n  /**\n   * @dev See {IERC165-supportsInterface}.\n   */\n  function supportsInterface(bytes4 interfaceId)\n    public\n    view\n    virtual\n    override\n    returns (bool)\n  {\n    return\n      interfaceId == type(IAccessControl).interfaceId ||\n      super.supportsInterface(interfaceId);\n  }\n\n  /**\n   * @dev Returns `true` if `account` has been granted `role`.\n   */\n  function hasRole(bytes32 role, address account)\n    public\n    view\n    virtual\n    override\n    returns (bool)\n  {\n    return _roles[role].members[account];\n  }\n\n  /**\n   * @dev Revert with a standard message if `account` is missing `role`.\n   *\n   * The format of the revert reason is given by the following regular expression:\n   *\n   *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n   */\n  function _checkRole(bytes32 role, address account) internal view virtual {\n    if (!hasRole(role, account)) {\n      revert(\n        string(\n          abi.encodePacked(\n            \"AccessControl: account \",\n            Strings.toHexString(uint160(account), 20),\n            \" is missing role \",\n            Strings.toHexString(uint256(role), 32)\n          )\n        )\n      );\n    }\n  }\n\n  /**\n   * @dev Returns the admin role that controls `role`. See {grantRole} and\n   * {revokeRole}.\n   *\n   * To change a role's admin, use {_setRoleAdmin}.\n   */\n  function getRoleAdmin(bytes32 role)\n    public\n    view\n    virtual\n    override\n    returns (bytes32)\n  {\n    return _roles[role].adminRole;\n  }\n\n  /**\n   * @dev Grants `role` to `account`.\n   *\n   * If `account` had not been already granted `role`, emits a {RoleGranted}\n   * event.\n   *\n   * Requirements:\n   *\n   * - the caller must have ``role``'s admin role.\n   */\n  function grantRole(bytes32 role, address account)\n    public\n    virtual\n    override\n    onlyRole(getRoleAdmin(role))\n  {\n    _grantRole(role, account);\n  }\n\n  /**\n   * @dev Revokes `role` from `account`.\n   *\n   * If `account` had been granted `role`, emits a {RoleRevoked} event.\n   *\n   * Requirements:\n   *\n   * - the caller must have ``role``'s admin role.\n   */\n  function revokeRole(bytes32 role, address account)\n    public\n    virtual\n    override\n    onlyRole(getRoleAdmin(role))\n  {\n    _revokeRole(role, account);\n  }\n\n  /**\n   * @dev Revokes `role` from the calling account.\n   *\n   * Roles are often managed via {grantRole} and {revokeRole}: this function's\n   * purpose is to provide a mechanism for accounts to lose their privileges\n   * if they are compromised (such as when a trusted device is misplaced).\n   *\n   * If the calling account had been revoked `role`, emits a {RoleRevoked}\n   * event.\n   *\n   * Requirements:\n   *\n   * - the caller must be `account`.\n   */\n  function renounceRole(bytes32 role, address account) public virtual override {\n    require(\n      account == _msgSender(),\n      \"AccessControl: can only renounce roles for self\"\n    );\n\n    _revokeRole(role, account);\n  }\n\n  /**\n   * @dev Grants `role` to `account`.\n   *\n   * If `account` had not been already granted `role`, emits a {RoleGranted}\n   * event. Note that unlike {grantRole}, this function doesn't perform any\n   * checks on the calling account.\n   *\n   * [WARNING]\n   * ====\n   * This function should only be called from the constructor when setting\n   * up the initial roles for the system.\n   *\n   * Using this function in any other way is effectively circumventing the admin\n   * system imposed by {AccessControl}.\n   * ====\n   *\n   * NOTE: This function is deprecated in favor of {_grantRole}.\n   */\n  function _setupRole(bytes32 role, address account) internal virtual {\n    _grantRole(role, account);\n  }\n\n  /**\n   * @dev Sets `adminRole` as ``role``'s admin role.\n   *\n   * Emits a {RoleAdminChanged} event.\n   */\n  function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n    bytes32 previousAdminRole = getRoleAdmin(role);\n    _roles[role].adminRole = adminRole;\n    emit RoleAdminChanged(role, previousAdminRole, adminRole);\n  }\n\n  /**\n   * @dev Grants `role` to `account`.\n   *\n   * Internal function without access restriction.\n   */\n  function _grantRole(bytes32 role, address account) internal virtual {\n    if (!hasRole(role, account)) {\n      _roles[role].members[account] = true;\n      emit RoleGranted(role, account, _msgSender());\n    }\n  }\n\n  /**\n   * @dev Revokes `role` from `account`.\n   *\n   * Internal function without access restriction.\n   */\n  function _revokeRole(bytes32 role, address account) internal virtual {\n    if (hasRole(role, account)) {\n      _roles[role].members[account] = false;\n      emit RoleRevoked(role, account, _msgSender());\n    }\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/access/AccessControlEnumerable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/access/IAccessControlEnumerable.sol\";\nimport \"contracts/external/openzeppelin/contracts/access/AccessControl.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is\n  IAccessControlEnumerable,\n  AccessControl\n{\n  using EnumerableSet for EnumerableSet.AddressSet;\n\n  mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n  /**\n   * @dev See {IERC165-supportsInterface}.\n   */\n  function supportsInterface(bytes4 interfaceId)\n    public\n    view\n    virtual\n    override\n    returns (bool)\n  {\n    return\n      interfaceId == type(IAccessControlEnumerable).interfaceId ||\n      super.supportsInterface(interfaceId);\n  }\n\n  /**\n   * @dev Returns one of the accounts that have `role`. `index` must be a\n   * value between 0 and {getRoleMemberCount}, non-inclusive.\n   *\n   * Role bearers are not sorted in any particular way, and their ordering may\n   * change at any point.\n   *\n   * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n   * you perform all queries on the same block. See the following\n   * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n   * for more information.\n   */\n  function getRoleMember(bytes32 role, uint256 index)\n    public\n    view\n    virtual\n    override\n    returns (address)\n  {\n    return _roleMembers[role].at(index);\n  }\n\n  /**\n   * @dev Returns the number of accounts that have `role`. Can be used\n   * together with {getRoleMember} to enumerate all bearers of a role.\n   */\n  function getRoleMemberCount(bytes32 role)\n    public\n    view\n    virtual\n    override\n    returns (uint256)\n  {\n    return _roleMembers[role].length();\n  }\n\n  /**\n   * @dev Overload {_grantRole} to track enumerable memberships\n   */\n  function _grantRole(bytes32 role, address account) internal virtual override {\n    super._grantRole(role, account);\n    _roleMembers[role].add(account);\n  }\n\n  /**\n   * @dev Overload {_revokeRole} to track enumerable memberships\n   */\n  function _revokeRole(bytes32 role, address account)\n    internal\n    virtual\n    override\n  {\n    super._revokeRole(role, account);\n    _roleMembers[role].remove(account);\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n  /**\n   * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n   *\n   * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n   * {RoleAdminChanged} not being emitted signaling this.\n   *\n   * _Available since v3.1._\n   */\n  event RoleAdminChanged(\n    bytes32 indexed role,\n    bytes32 indexed previousAdminRole,\n    bytes32 indexed newAdminRole\n  );\n\n  /**\n   * @dev Emitted when `account` is granted `role`.\n   *\n   * `sender` is the account that originated the contract call, an admin role\n   * bearer except when using {AccessControl-_setupRole}.\n   */\n  event RoleGranted(\n    bytes32 indexed role,\n    address indexed account,\n    address indexed sender\n  );\n\n  /**\n   * @dev Emitted when `account` is revoked `role`.\n   *\n   * `sender` is the account that originated the contract call:\n   *   - if using `revokeRole`, it is the admin role bearer\n   *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n   */\n  event RoleRevoked(\n    bytes32 indexed role,\n    address indexed account,\n    address indexed sender\n  );\n\n  /**\n   * @dev Returns `true` if `account` has been granted `role`.\n   */\n  function hasRole(bytes32 role, address account) external view returns (bool);\n\n  /**\n   * @dev Returns the admin role that controls `role`. See {grantRole} and\n   * {revokeRole}.\n   *\n   * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n   */\n  function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n  /**\n   * @dev Grants `role` to `account`.\n   *\n   * If `account` had not been already granted `role`, emits a {RoleGranted}\n   * event.\n   *\n   * Requirements:\n   *\n   * - the caller must have ``role``'s admin role.\n   */\n  function grantRole(bytes32 role, address account) external;\n\n  /**\n   * @dev Revokes `role` from `account`.\n   *\n   * If `account` had been granted `role`, emits a {RoleRevoked} event.\n   *\n   * Requirements:\n   *\n   * - the caller must have ``role``'s admin role.\n   */\n  function revokeRole(bytes32 role, address account) external;\n\n  /**\n   * @dev Revokes `role` from the calling account.\n   *\n   * Roles are often managed via {grantRole} and {revokeRole}: this function's\n   * purpose is to provide a mechanism for accounts to lose their privileges\n   * if they are compromised (such as when a trusted device is misplaced).\n   *\n   * If the calling account had been granted `role`, emits a {RoleRevoked}\n   * event.\n   *\n   * Requirements:\n   *\n   * - the caller must be `account`.\n   */\n  function renounceRole(bytes32 role, address account) external;\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/access/IAccessControlEnumerable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n  /**\n   * @dev Returns one of the accounts that have `role`. `index` must be a\n   * value between 0 and {getRoleMemberCount}, non-inclusive.\n   *\n   * Role bearers are not sorted in any particular way, and their ordering may\n   * change at any point.\n   *\n   * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n   * you perform all queries on the same block. See the following\n   * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n   * for more information.\n   */\n  function getRoleMember(bytes32 role, uint256 index)\n    external\n    view\n    returns (address);\n\n  /**\n   * @dev Returns the number of accounts that have `role`. Can be used\n   * together with {getRoleMember} to enumerate all bearers of a role.\n   */\n  function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/security/ReentrancyGuard.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n  // Booleans are more expensive than uint256 or any type that takes up a full\n  // word because each write operation emits an extra SLOAD to first read the\n  // slot's contents, replace the bits taken up by the boolean, and then write\n  // back. This is the compiler's defense against contract upgrades and\n  // pointer aliasing, and it cannot be disabled.\n\n  // The values being non-zero value makes deployment a bit more expensive,\n  // but in exchange the refund on every call to nonReentrant will be lower in\n  // amount. Since refunds are capped to a percentage of the total\n  // transaction's gas, it is best to keep them low in cases like this one, to\n  // increase the likelihood of the full refund coming into effect.\n  uint256 private constant _NOT_ENTERED = 1;\n  uint256 private constant _ENTERED = 2;\n\n  uint256 private _status;\n\n  constructor() {\n    _status = _NOT_ENTERED;\n  }\n\n  /**\n   * @dev Prevents a contract from calling itself, directly or indirectly.\n   * Calling a `nonReentrant` function from another `nonReentrant`\n   * function is not supported. It is possible to prevent this from happening\n   * by making the `nonReentrant` function external, and making it call a\n   * `private` function that does the actual work.\n   */\n  modifier nonReentrant() {\n    // On the first call to nonReentrant, _notEntered will be true\n    require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n    // Any calls to nonReentrant after this point will fail\n    _status = _ENTERED;\n\n    _;\n\n    // By storing the original value once again, a refund is triggered (see\n    // https://eips.ethereum.org/EIPS/eip-2200)\n    _status = _NOT_ENTERED;\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/token/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n  /**\n   * @dev Returns the amount of tokens in existence.\n   */\n  function totalSupply() external view returns (uint256);\n\n  /**\n   * @dev Returns the amount of tokens owned by `account`.\n   */\n  function balanceOf(address account) external view returns (uint256);\n\n  /**\n   * @dev Moves `amount` tokens from the caller's account to `to`.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a {Transfer} event.\n   */\n  function transfer(address to, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Returns the remaining number of tokens that `spender` will be\n   * allowed to spend on behalf of `owner` through {transferFrom}. This is\n   * zero by default.\n   *\n   * This value changes when {approve} or {transferFrom} are called.\n   */\n  function allowance(address owner, address spender)\n    external\n    view\n    returns (uint256);\n\n  /**\n   * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * IMPORTANT: Beware that changing an allowance with this method brings the risk\n   * that someone may use both the old and the new allowance by unfortunate\n   * transaction ordering. One possible solution to mitigate this race\n   * condition is to first reduce the spender's allowance to 0 and set the\n   * desired value afterwards:\n   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n   *\n   * Emits an {Approval} event.\n   */\n  function approve(address spender, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Moves `amount` tokens from `from` to `to` using the\n   * allowance mechanism. `amount` is then deducted from the caller's\n   * allowance.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a {Transfer} event.\n   */\n  function transferFrom(\n    address from,\n    address to,\n    uint256 amount\n  ) external returns (bool);\n\n  /**\n   * @dev Emitted when `value` tokens are moved from one account (`from`) to\n   * another (`to`).\n   *\n   * Note that `value` may be zero.\n   */\n  event Transfer(address indexed from, address indexed to, uint256 value);\n\n  /**\n   * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n   * a call to {approve}. `value` is the new allowance.\n   */\n  event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/token/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/token/IERC20.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     *\n     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            // bubble errors\n            if iszero(success) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n\n        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        bool success;\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\n    }\n}"},{"file_path":"contracts/external/openzeppelin/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n  function _msgSender() internal view virtual returns (address) {\n    return msg.sender;\n  }\n\n  function _msgData() internal view virtual returns (bytes calldata) {\n    return msg.data;\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/ERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/utils/IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n  /**\n   * @dev See {IERC165-supportsInterface}.\n   */\n  function supportsInterface(bytes4 interfaceId)\n    public\n    view\n    virtual\n    override\n    returns (bool)\n  {\n    return interfaceId == type(IERC165).interfaceId;\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/EnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n  // To implement this library for multiple types with as little code\n  // repetition as possible, we write it in terms of a generic Set type with\n  // bytes32 values.\n  // The Set implementation uses private functions, and user-facing\n  // implementations (such as AddressSet) are just wrappers around the\n  // underlying Set.\n  // This means that we can only create new EnumerableSets for types that fit\n  // in bytes32.\n\n  struct Set {\n    // Storage of set values\n    bytes32[] _values;\n    // Position of the value in the `values` array, plus 1 because index 0\n    // means a value is not in the set.\n    mapping(bytes32 => uint256) _indexes;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function _add(Set storage set, bytes32 value) private returns (bool) {\n    if (!_contains(set, value)) {\n      set._values.push(value);\n      // The value is stored at length-1, but we add 1 to all indexes\n      // and use 0 as a sentinel value\n      set._indexes[value] = set._values.length;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function _remove(Set storage set, bytes32 value) private returns (bool) {\n    // We read and store the value's index to prevent multiple reads from the same storage slot\n    uint256 valueIndex = set._indexes[value];\n\n    if (valueIndex != 0) {\n      // Equivalent to contains(set, value)\n      // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n      // the array, and then remove the last element (sometimes called as 'swap and pop').\n      // This modifies the order of the array, as noted in {at}.\n\n      uint256 toDeleteIndex = valueIndex - 1;\n      uint256 lastIndex = set._values.length - 1;\n\n      if (lastIndex != toDeleteIndex) {\n        bytes32 lastvalue = set._values[lastIndex];\n\n        // Move the last value to the index where the value to delete is\n        set._values[toDeleteIndex] = lastvalue;\n        // Update the index for the moved value\n        set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\n      }\n\n      // Delete the slot where the moved value was stored\n      set._values.pop();\n\n      // Delete the index for the deleted slot\n      delete set._indexes[value];\n\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function _contains(Set storage set, bytes32 value)\n    private\n    view\n    returns (bool)\n  {\n    return set._indexes[value] != 0;\n  }\n\n  /**\n   * @dev Returns the number of values on the set. O(1).\n   */\n  function _length(Set storage set) private view returns (uint256) {\n    return set._values.length;\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function _at(Set storage set, uint256 index) private view returns (bytes32) {\n    return set._values[index];\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function _values(Set storage set) private view returns (bytes32[] memory) {\n    return set._values;\n  }\n\n  // Bytes32Set\n\n  struct Bytes32Set {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n    return _add(set._inner, value);\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(Bytes32Set storage set, bytes32 value)\n    internal\n    returns (bool)\n  {\n    return _remove(set._inner, value);\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(Bytes32Set storage set, bytes32 value)\n    internal\n    view\n    returns (bool)\n  {\n    return _contains(set._inner, value);\n  }\n\n  /**\n   * @dev Returns the number of values in the set. O(1).\n   */\n  function length(Bytes32Set storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(Bytes32Set storage set, uint256 index)\n    internal\n    view\n    returns (bytes32)\n  {\n    return _at(set._inner, index);\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(Bytes32Set storage set)\n    internal\n    view\n    returns (bytes32[] memory)\n  {\n    return _values(set._inner);\n  }\n\n  // AddressSet\n\n  struct AddressSet {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(AddressSet storage set, address value) internal returns (bool) {\n    return _add(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(AddressSet storage set, address value)\n    internal\n    returns (bool)\n  {\n    return _remove(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(AddressSet storage set, address value)\n    internal\n    view\n    returns (bool)\n  {\n    return _contains(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Returns the number of values in the set. O(1).\n   */\n  function length(AddressSet storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(AddressSet storage set, uint256 index)\n    internal\n    view\n    returns (address)\n  {\n    return address(uint160(uint256(_at(set._inner, index))));\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(AddressSet storage set)\n    internal\n    view\n    returns (address[] memory)\n  {\n    bytes32[] memory store = _values(set._inner);\n    address[] memory result;\n\n    assembly {\n      result := store\n    }\n\n    return result;\n  }\n\n  // UintSet\n\n  struct UintSet {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(UintSet storage set, uint256 value) internal returns (bool) {\n    return _add(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(UintSet storage set, uint256 value) internal returns (bool) {\n    return _remove(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(UintSet storage set, uint256 value)\n    internal\n    view\n    returns (bool)\n  {\n    return _contains(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Returns the number of values on the set. O(1).\n   */\n  function length(UintSet storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(UintSet storage set, uint256 index)\n    internal\n    view\n    returns (uint256)\n  {\n    return uint256(_at(set._inner, index));\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(UintSet storage set)\n    internal\n    view\n    returns (uint256[] memory)\n  {\n    bytes32[] memory store = _values(set._inner);\n    uint256[] memory result;\n\n    assembly {\n      result := store\n    }\n\n    return result;\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n  /**\n   * @dev Returns true if this contract implements the interface defined by\n   * `interfaceId`. See the corresponding\n   * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n   * to learn more about how these ids are created.\n   *\n   * This function call must use less than 30 000 gas.\n   */\n  function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/Strings.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n  bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n  /**\n   * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n   */\n  function toString(uint256 value) internal pure returns (string memory) {\n    // Inspired by OraclizeAPI's implementation - MIT licence\n    // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n    if (value == 0) {\n      return \"0\";\n    }\n    uint256 temp = value;\n    uint256 digits;\n    while (temp != 0) {\n      digits++;\n      temp /= 10;\n    }\n    bytes memory buffer = new bytes(digits);\n    while (value != 0) {\n      digits -= 1;\n      buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n      value /= 10;\n    }\n    return string(buffer);\n  }\n\n  /**\n   * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n   */\n  function toHexString(uint256 value) internal pure returns (string memory) {\n    if (value == 0) {\n      return \"0x00\";\n    }\n    uint256 temp = value;\n    uint256 length = 0;\n    while (temp != 0) {\n      length++;\n      temp >>= 8;\n    }\n    return toHexString(value, length);\n  }\n\n  /**\n   * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n   */\n  function toHexString(uint256 value, uint256 length)\n    internal\n    pure\n    returns (string memory)\n  {\n    bytes memory buffer = new bytes(2 * length + 2);\n    buffer[0] = \"0\";\n    buffer[1] = \"x\";\n    for (uint256 i = 2 * length + 1; i > 1; --i) {\n      buffer[i] = _HEX_SYMBOLS[value & 0xf];\n      value >>= 4;\n    }\n    require(value == 0, \"Strings: hex length insufficient\");\n    return string(buffer);\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/cryptography/ECDSA.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV // Deprecated in v4.8\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert(\"ECDSA: invalid signature\");\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert(\"ECDSA: invalid signature length\");\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength);\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address, RecoverError) {\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\n        return tryRecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     *\n     * _Available since v4.2._\n     */\n    function recover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n    }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/cryptography/EIP712.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n    /* solhint-disable var-name-mixedcase */\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n    // invalidate the cached domain separator if the chain id changes.\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n    uint256 private immutable _CACHED_CHAIN_ID;\n    address private immutable _CACHED_THIS;\n\n    bytes32 private immutable _HASHED_NAME;\n    bytes32 private immutable _HASHED_VERSION;\n    bytes32 private immutable _TYPE_HASH;\n\n    /* solhint-enable var-name-mixedcase */\n\n    /**\n     * @dev Initializes the domain separator and parameter caches.\n     *\n     * The meaning of `name` and `version` is specified in\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n     *\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n     * - `version`: the current major version of the signing domain.\n     *\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n     * contract upgrade].\n     */\n    constructor(string memory name, string memory version) {\n        bytes32 hashedName = keccak256(bytes(name));\n        bytes32 hashedVersion = keccak256(bytes(version));\n        bytes32 typeHash = keccak256(\n            \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n        );\n        _HASHED_NAME = hashedName;\n        _HASHED_VERSION = hashedVersion;\n        _CACHED_CHAIN_ID = block.chainid;\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n        _CACHED_THIS = address(this);\n        _TYPE_HASH = typeHash;\n    }\n\n    /**\n     * @dev Returns the domain separator for the current chain.\n     */\n    function _domainSeparatorV4() internal view returns (bytes32) {\n        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n            return _CACHED_DOMAIN_SEPARATOR;\n        } else {\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n        }\n    }\n\n    function _buildDomainSeparator(\n        bytes32 typeHash,\n        bytes32 nameHash,\n        bytes32 versionHash\n    ) private view returns (bytes32) {\n        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n    }\n\n    /**\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n     * function returns the hash of the fully encoded EIP712 message for this domain.\n     *\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n     *\n     * ```solidity\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n     *     keccak256(\"Mail(address to,string contents)\"),\n     *     mailTo,\n     *     keccak256(bytes(mailContents))\n     * )));\n     * address signer = ECDSA.recover(digest, signature);\n     * ```\n     */\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n    }\n}\n"},{"file_path":"contracts/globalMarkets/USDonManager/IUSDonManager.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n/*\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\n/**\n * @title  IUSDonManager\n * @author Ondo Finance\n * @notice This contract provides an interface for conducting instant USDon swaps.\n */\ninterface IUSDonManager {\n  function subscribe(\n    address depositToken,\n    uint256 depositAmount,\n    uint256 minimumRwaReceived\n  ) external returns (uint256 rwaAmountOut);\n\n  function redeem(\n    uint256 rwaAmount,\n    address receivingToken,\n    uint256 minimumTokenReceived\n  ) external returns (uint256 receiveTokenAmount);\n}\n"},{"file_path":"contracts/globalMarkets/tokenManager/IGMTokenManager.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\n\npragma solidity 0.8.16;\n\n/**\n * @title  IGMTokenManager\n * @author Ondo Finance\n * @notice Interface for interacting with the GMTokenManager contract\n */\ninterface IGMTokenManager {\n  enum QuoteSide {\n    /// Indicates that the user is buying GM tokens\n    BUY,\n    /// Indicates that the user is selling GM tokens\n    SELL\n  }\n\n  /**\n   * @notice Quote struct that is signed by the attestation signer\n   * @param  attestationId  The ID of the quote\n   * @param  chainId        The chain ID of the quote is intended for\n   * @param  userId         The user ID the quote is intended for\n   * @param  asset          The address of the GM token being bought or sold\n   * @param  price          The price of the GM token in USD with 18 decimals\n   * @param  quantity       The quantity of GM tokens being bought or sold\n   * @param  expiration     The expiration of the quote in seconds since the epoch\n   * @param  side           The direction of the quote (BUY or SELL)\n   * @param  additionalData Any additional data that is needed for the quote\n   */\n  struct Quote {\n    uint256 chainId;\n    uint256 attestationId;\n    bytes32 userId;\n    address asset;\n    uint256 price;\n    uint256 quantity;\n    uint256 expiration;\n    QuoteSide side;\n    bytes32 additionalData;\n  }\n\n  /**\n   * @notice Event emitted when a trade is executed with an attestation\n   * @param  executionId    The monotonically increasing ID of the trade\n   * @param  attestationId  The ID of the quote\n   * @param  chainId        The chain ID the quote is intended to be used\n   * @param  userId         The user ID the quote is intended for\n   * @param  side           The direction of the quote (BUY or SELL)\n   * @param  asset          The address of the GM token being bought or sold\n   * @param  price          The price of the GM token in USD with 18 decimals\n   * @param  quantity       The quantity of GM tokens being bought or sold\n   * @param  expiration     The expiration of the quote in seconds since the epoch\n   * @param  additionalData Any additional data that is needed for the quote\n   */\n  event TradeExecuted(\n    uint256 executionId,\n    uint256 attestationId,\n    uint256 chainId,\n    bytes32 userId,\n    QuoteSide side,\n    address asset,\n    uint256 price,\n    uint256 quantity,\n    uint256 expiration,\n    bytes32 additionalData\n  );\n\n  function mintWithAttestation(\n    Quote calldata quote,\n    bytes memory signature,\n    address depositToken,\n    uint256 depositAmount\n  ) external returns (uint256 receivedGmTokenAmount);\n\n  function redeemWithAttestation(\n    Quote calldata quote,\n    bytes memory signature,\n    address receiveToken,\n    uint256 minimumReceiveAmount\n  ) external returns (uint256 redemptionUSDonValue);\n}\n"},{"file_path":"contracts/globalMarkets/tokenManager/IGMTokenManagerErrors.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n/*\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\n/**\n * @title  IGMTokenManagerErrors\n * @author Ondo Finance\n * @notice Isolated contract for all errors emitted by the GMTokenManager contract\n */\ninterface IGMTokenManagerErrors {\n  /// Error emitted when the token address is zero\n  error TokenAddressCantBeZero();\n\n  /// Error emitted when the deposit amount is too small\n  error DepositAmountTooSmall();\n\n  /// Error emitted when the user is not registered with the ID registry\n  error UserNotRegistered();\n\n  /// Error emitted when the redemption amount is too small\n  error RedemptionAmountTooSmall();\n\n  /// Error emitted when attempting to set the `OndoIDRegistry` address to zero\n  error IDRegistryAddressCantBeZero();\n\n  /// Error emitted when attempting to set the `OndoRateLimiter` address to zero\n  error RateLimiterAddressCantBeZero();\n\n  /// Error emitted when the minting functionality is paused\n  error GlobalMintsPaused();\n\n  /// Error emitted when the redemption functionality is paused\n  error GlobalRedemptionsPaused();\n\n  /// Error emitted when the minting functionality is paused for a specific token\n  error GMTokenMintsPaused();\n\n  /// Error emitted when the redemption functionality is paused for a specific token\n  error GMTokenRedemptionsPaused();\n\n  /// Error emitted attempting to set the `OndoSanityCheckOracle` address to zero\n  error SanityCheckOracleAddressCantBeZero();\n\n  /// Custom error for expired attestations\n  error AttestationExpired();\n\n  /// Custom error for attestion signed by unverifid signer\n  error InvalidAttestationSigner();\n\n  /// Custom error for invalid chain ID\n  error InvalidChainId();\n\n  /// Custom error for invalid quote direction\n  error InvalidQuoteSide();\n\n  /// Custom error for user ID mismatch\n  error UserIdMismatch(bytes32 expected, bytes32 actual);\n\n  /// Custom error for already redeemed attestations\n  error AttestationAlreadyExecuted();\n\n  /// Error emitted when attempting to set the `IssuanceHours` address to zero\n  error IssuanceHoursAddressCantBeZero();\n\n  // Error emitted when attempting to use an USDon manager reliant function when the USDon manager is set to zero\n  error USDonManagerNotEnabled();\n\n  /// Error emitted when the GM Token is not registered for minting/redemption\n  error GMTokenNotRegistered();\n\n  /// Error emitted when attempting to set the `USDon` address to zero\n  error USDonAddressCantBeZero();\n}\n"},{"file_path":"contracts/globalMarkets/tokenManager/IGMTokenManagerEvents.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n/*\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\n/**\n * @title  IGMTokenManagerEvents\n * @author Ondo Finance\n * @notice Isolated contract for all events emitted by the GMTokenManager contract\n */\ninterface IGMTokenManagerEvents {\n  /**\n   * @notice Event emitted when an admin completes a mint for a recipient\n   * @param  recipient    The address of the recipient that receives the RWA tokens\n   * @param  recipientId  The user ID of the recipient\n   * @param  rwaToken     The address of the RWA token being minted\n   * @param  rwaAmount    The amount of RWA tokens minted in decimals of the RWA token\n   * @param  metadata     Additional metadata to associate with the mint\n   */\n  event AdminMint(\n    address indexed recipient,\n    bytes32 indexed recipientId,\n    address indexed rwaToken,\n    uint256 rwaAmount,\n    bytes32 metadata\n  );\n\n  /**\n   * @notice Event emitted when the `OndoIDRegistry` contract is set\n   * @param  oldOndoIDRegistry The old `OndoIDRegistry` contract address\n   * @param  newOndoIDRegistry The new `OndoIDRegistry` contract address\n   */\n  event OndoIDRegistrySet(\n    address indexed oldOndoIDRegistry,\n    address indexed newOndoIDRegistry\n  );\n\n  /**\n   * @notice Event emitted when the `OndoRateLimiter` contract is set\n   * @param  oldOndoRateLimiter The old `OndoRateLimiter` contract address\n   * @param  newOndoRateLimiter The new `OndoRateLimiter` contract address\n   */\n  event OndoRateLimiterSet(\n    address indexed oldOndoRateLimiter,\n    address indexed newOndoRateLimiter\n  );\n\n  /**\n   * @notice Event emitted when subscription minimum is set\n   * @param  oldMinDepositAmount Old subscription minimum\n   * @param  newMinDepositAmount New subscription minimum\n   */\n  event MinimumDepositAmountSet(\n    uint256 indexed oldMinDepositAmount,\n    uint256 indexed newMinDepositAmount\n  );\n\n  /**\n   * @notice Event emitted when redeem minimum is set\n   * @param  oldMinRedemptionAmount Old redeem minimum\n   * @param  newMinRedemptionAmount New redeem minimum\n   */\n  event MinimumRedemptionAmountSet(\n    uint256 indexed oldMinRedemptionAmount,\n    uint256 indexed newMinRedemptionAmount\n  );\n\n  /**\n   * @notice Event emitted when the `OndoSanityCheckOracle` contract is set\n   * @param  oldOndoSanityCheckOracle The old `OndoSanityCheckOracle` contract address\n   * @param  newOndoSanityCheckOracle The new `OndoSanityCheckOracle` contract address\n   */\n  event OndoSanityCheckOracleSet(\n    address indexed oldOndoSanityCheckOracle,\n    address indexed newOndoSanityCheckOracle\n  );\n\n  /**\n   * @notice Event emitted when the `IssuanceHours` contract is set\n   * @param  oldIssuanceHours The old `IssuanceHours` contract address\n   * @param  newIssuanceHours The new `IssuanceHours` contract address\n   */\n  event IssuanceHoursSet(\n    address indexed oldIssuanceHours,\n    address indexed newIssuanceHours\n  );\n\n  /**\n   * @notice Event emitted when the `USDonManager` contract is set\n   * @param  oldUSDonManager The old `USDonManager` contract address\n   * @param  newUSDonManager The new `USDonManager` contract address\n   */\n  event USDonManagerSet(\n    address indexed oldUSDonManager,\n    address indexed newUSDonManager\n  );\n\n  /**\n   * @notice Event emitted when the accepted GM token is set\n   * @param  gmToken    The address of the GM token\n   * @param  registered Whether the GM token is registered\n   */\n  event GMTokenRegistered(address indexed gmToken, bool indexed registered);\n\n  /// Event emitted when minting functionality is paused\n  event GlobalMintingPaused();\n\n  /// Event emitted when minting functionality is unpaused\n  event GlobalMintingUnpaused();\n\n  /// Event emitted when redeem functionality is paused\n  event GlobalRedeemingPaused();\n\n  /// Event emitted when redeem functionality is unpaused\n  event GlobalRedeemingUnpaused();\n\n  /**\n   * @notice Event emitted when minting is paused for a specific GM token\n   * @param gmToken The address of the GM token\n   */\n  event GMTokenMintingPaused(address indexed gmToken);\n\n  /**\n   * @notice Event emitted when minting is unpaused for a specific GM token\n   * @param gmToken The address of the GM token\n   */\n  event GMTokenMintingUnpaused(address indexed gmToken);\n\n  /**\n   * @notice Event emitted when redemption is paused for a specific GM token\n   * @param gmToken The address of the GM token\n   */\n  event GMTokenRedeemingPaused(address indexed gmToken);\n\n  /**\n   * @notice Event emitted when redemption is unpaused for a specific GM token\n   * @param gmToken The address of the GM token\n   */\n  event GMTokenRedeemingUnpaused(address indexed gmToken);\n}\n"},{"file_path":"contracts/globalMarkets/tokenManager/issuanceHours/IIssuanceHours.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n/*\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\n/**\n * @title  IIssuanceHours\n * @author Ondo Finance\n * @notice Interface for checking if current time is within valid market hours\n */\ninterface IIssuanceHours {\n  function checkIsValidHours() external;\n}\n"},{"file_path":"contracts/globalMarkets/tokenManager/sanityCheckOracle/IOndoSanityCheckOracle.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\n\npragma solidity 0.8.16;\n\n/**\n * @title  IOndoSanityCheckOracle\n * @author Ondo Finance\n * @notice Interface for validating prices with the sanity check oracle\n */\ninterface IOndoSanityCheckOracle {\n  function validatePrice(address token, uint256 price) external view;\n}\n"},{"file_path":"contracts/interfaces/IRWALike.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\n// This interface is not inherited directly by RWA, instead, it is a\n// subset of functions provided by all RWA tokens that the RWA Hub\n// Client uses.\nimport \"contracts/external/openzeppelin/contracts/token/IERC20.sol\";\n\ninterface IRWALike is IERC20 {\n  function mint(address to, uint256 amount) external;\n\n  function burn(uint256 amount) external;\n\n  function burnFrom(address from, uint256 amount) external;\n}\n"},{"file_path":"contracts/xManager/interfaces/IOndoIDRegistry.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n/*\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\ninterface IOndoIDRegistry {\n  function getRegisteredID(\n    address rwaToken,\n    address user\n  ) external view returns (bytes32 userID);\n}\n"},{"file_path":"contracts/xManager/interfaces/IOndoRateLimiter.sol","source_code":"// SPDX-License-Identifier: MIT\n/*\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\ninterface IOndoRateLimiter {\n  enum TransactionType {\n    SUBSCRIPTION,\n    REDEMPTION\n  }\n\n  function checkAndUpdateRateLimit(\n    TransactionType transactionType,\n    address rwaToken,\n    bytes32 userID,\n    uint256 usdValue\n  ) external;\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_defaultAdmin","type":"address"},{"internalType":"address","name":"_usdon","type":"address"},{"internalType":"uint256","name":"_minimumDepositUSD","type":"uint256"},{"internalType":"uint256","name":"_minimumRedemptionUSD","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AttestationAlreadyExecuted","type":"error"},{"inputs":[],"name":"AttestationExpired","type":"error"},{"inputs":[],"name":"DepositAmountTooSmall","type":"error"},{"inputs":[],"name":"GMTokenMintsPaused","type":"error"},{"inputs":[],"name":"GMTokenNotRegistered","type":"error"},{"inputs":[],"name":"GMTokenRedemptionsPaused","type":"error"},{"inputs":[],"name":"GlobalMintsPaused","type":"error"},{"inputs":[],"name":"GlobalRedemptionsPaused","type":"error"},{"inputs":[],"name":"IDRegistryAddressCantBeZero","type":"error"},{"inputs":[],"name":"InvalidAttestationSigner","type":"error"},{"inputs":[],"name":"InvalidChainId","type":"error"},{"inputs":[],"name":"InvalidQuoteSide","type":"error"},{"inputs":[],"name":"IssuanceHoursAddressCantBeZero","type":"error"},{"inputs":[],"name":"RateLimiterAddressCantBeZero","type":"error"},{"inputs":[],"name":"RedemptionAmountTooSmall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SanityCheckOracleAddressCantBeZero","type":"error"},{"inputs":[],"name":"TokenAddressCantBeZero","type":"error"},{"inputs":[],"name":"USDonAddressCantBeZero","type":"error"},{"inputs":[],"name":"USDonManagerNotEnabled","type":"error"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"name":"UserIdMismatch","type":"error"},{"inputs":[],"name":"UserNotRegistered","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"bytes32","name":"recipientId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"rwaToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"rwaAmount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"metadata","type":"bytes32"}],"name":"AdminMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gmToken","type":"address"}],"name":"GMTokenMintingPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gmToken","type":"address"}],"name":"GMTokenMintingUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gmToken","type":"address"}],"name":"GMTokenRedeemingPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gmToken","type":"address"}],"name":"GMTokenRedeemingUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gmToken","type":"address"},{"indexed":true,"internalType":"bool","name":"registered","type":"bool"}],"name":"GMTokenRegistered","type":"event"},{"anonymous":false,"inputs":[],"name":"GlobalMintingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"GlobalMintingUnpaused","type":"event"},{"anonymous":false,"inputs":[],"name":"GlobalRedeemingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"GlobalRedeemingUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldIssuanceHours","type":"address"},{"indexed":true,"internalType":"address","name":"newIssuanceHours","type":"address"}],"name":"IssuanceHoursSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldMinDepositAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newMinDepositAmount","type":"uint256"}],"name":"MinimumDepositAmountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldMinRedemptionAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newMinRedemptionAmount","type":"uint256"}],"name":"MinimumRedemptionAmountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOndoIDRegistry","type":"address"},{"indexed":true,"internalType":"address","name":"newOndoIDRegistry","type":"address"}],"name":"OndoIDRegistrySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOndoRateLimiter","type":"address"},{"indexed":true,"internalType":"address","name":"newOndoRateLimiter","type":"address"}],"name":"OndoRateLimiterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOndoSanityCheckOracle","type":"address"},{"indexed":true,"internalType":"address","name":"newOndoSanityCheckOracle","type":"address"}],"name":"OndoSanityCheckOracleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"executionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"attestationId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"userId","type":"bytes32"},{"indexed":false,"internalType":"enum IGMTokenManager.QuoteSide","name":"side","type":"uint8"},{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiration","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"additionalData","type":"bytes32"}],"name":"TradeExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldUSDonManager","type":"address"},{"indexed":true,"internalType":"address","name":"newUSDonManager","type":"address"}],"name":"USDonManagerSet","type":"event"},{"inputs":[],"name":"ADMIN_MINT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ATTESTATION_SIGNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONFIGURER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GM_NORMALIZER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNPAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gmToken","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"gmTokenAmount","type":"uint256"},{"internalType":"bytes32","name":"metadata","type":"bytes32"}],"name":"adminProcessMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"executedAttestationIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalMintingPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalRedeemingPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gmIdentifier","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gmTokenAccepted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gmTokenMintingPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gmTokenRedemptionsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"issuanceHours","outputs":[{"internalType":"contract IIssuanceHours","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumDepositUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumRedemptionUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"attestationId","type":"uint256"},{"internalType":"bytes32","name":"userId","type":"bytes32"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"enum IGMTokenManager.QuoteSide","name":"side","type":"uint8"},{"internalType":"bytes32","name":"additionalData","type":"bytes32"}],"internalType":"struct IGMTokenManager.Quote","name":"quote","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256","name":"depositTokenAmount","type":"uint256"}],"name":"mintWithAttestation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ondoIDRegistry","outputs":[{"internalType":"contract IOndoIDRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ondoRateLimiter","outputs":[{"internalType":"contract IOndoRateLimiter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gmToken","type":"address"}],"name":"pauseGMTokenMints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gmToken","type":"address"}],"name":"pauseGMTokenRedemptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseGlobalMints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseGlobalRedeems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"attestationId","type":"uint256"},{"internalType":"bytes32","name":"userId","type":"bytes32"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"enum IGMTokenManager.QuoteSide","name":"side","type":"uint8"},{"internalType":"bytes32","name":"additionalData","type":"bytes32"}],"internalType":"struct IGMTokenManager.Quote","name":"quote","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"receiveToken","type":"address"},{"internalType":"uint256","name":"minimumReceiveAmount","type":"uint256"}],"name":"redeemWithAttestation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"retrieveTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sanityCheckOracle","outputs":[{"internalType":"contract IOndoSanityCheckOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"accepted","type":"bool"}],"name":"setGMTokenRegistrationStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_issuanceHours","type":"address"}],"name":"setIssuanceHours","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumDepositUSD","type":"uint256"}],"name":"setMinimumDepositAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumRedemptionUSD","type":"uint256"}],"name":"setMinimumRedemptionAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ondoIDRegistry","type":"address"}],"name":"setOndoIDRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ondoRateLimiter","type":"address"}],"name":"setOndoRateLimiter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sanityCheckOracle","type":"address"}],"name":"setSanityCheckOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_usdonManager","type":"address"}],"name":"setUSDonManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gmToken","type":"address"}],"name":"unpauseGMTokenMints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gmToken","type":"address"}],"name":"unpauseGMTokenRedemptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseGlobalMints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseGlobalRedeems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdon","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdonManager","outputs":[{"internalType":"contract IUSDonManager","name":"","type":"address"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"0x00000000000000000000000054b5aae5bda007db744ea762460a96f24bc1f4ad000000000000000000000000ace8e719899f6e91831b18ae746c9a965c2119f10000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a7640000"}