creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/ousg/ousgInstantManager.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/external/openzeppelin/contracts/access/AccessControlEnumerable.sol\";\nimport \"contracts/external/openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"contracts/external/openzeppelin/contracts/token/IERC20Metadata.sol\";\nimport \"contracts/external/chainlink/AggregatorV3Interface.sol\";\nimport \"contracts/ousg/rOUSG.sol\";\nimport \"contracts/interfaces/IRWALike.sol\";\nimport \"contracts/external/circle/IRedemption.sol\";\nimport \"contracts/InstantMintTimeBasedRateLimiter.sol\";\nimport \"contracts/interfaces/IOUSGInstantManager.sol\";\nimport \"contracts/interfaces/IMulticall.sol\";\nimport \"contracts/interfaces/IInvestorBasedRateLimiter.sol\";\n\n/**\n * @title OUSGInstantManager\n * @author Ondo Finance\n * @notice This contract is responsible for minting\n *         and redeeming OUSG and rOUSG against USDC. Addresses\n *         with the DEFAULT_ADMIN_ROLE able to set optional mint and\n *         redeem fees. It is implemented in terms of a\n *         InstantMintTimeBasedRateLimiter, which imposes mint and redeem limits within\n *         specified intervals. Additionally, addresses with the PAUSER role in\n *         the registry can pause mints and redemptions, while addresses with\n *         the DEFAULT_ADMIN role can unpause mints or redemptions.\n *\n * @dev Please be aware of the differences of decimals representations between\n *      OUSG, rOUSG, USDC, and BUIDL. This contract multiplies\n *      or divides quantities by a scaling factor (see `decimalsMultiplier`) to\n *      account for this. Due to the way the difference in decimals is\n *      calculated, the decimals value of the usdc token MUST be less\n *      than or equal to OUSG's decimals value or else contract deployment\n *      will fail.\n */\ncontract OUSGInstantManager is\n  ReentrancyGuard,\n  InstantMintTimeBasedRateLimiter,\n  AccessControlEnumerable,\n  IOUSGInstantManager,\n  IMulticall\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 sweep tokens from the contract using retrieveTokens\n  bytes32 public constant RETRIEVER_ROLE = keccak256(\"RETRIEVER_ROLE\");\n\n  // Safety circuit breaker in case of Oracle malfunction\n  uint256 public constant MINIMUM_OUSG_PRICE = 105894206000000000000;\n\n  // Safety circuit breaker in case of USDC Depeg event\n  int256 public constant MINIMUM_USDC_PRICE = 995e5;\n\n  // Helper constant that allows us to precisely specify fees in basis points\n  uint256 public constant FEE_GRANULARITY = 10_000;\n\n  // Helper constant that allows us to convert between OUSG and rOUSG shares\n  uint256 public constant OUSG_TO_ROUSG_SHARES_MULTIPLIER = 10_000;\n\n  // USDC contract\n  IERC20 public immutable usdc; // 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n\n  // OUSG contract\n  IRWALike public immutable ousg;\n\n  // Rebasing OUSG Contract\n  ROUSG public immutable rousg;\n\n  // BUIDL token contract\n  IERC20 public immutable buidl;\n\n  // Redeemer contract used for instant redemptions of BUIDL\n  IRedemption public immutable buidlRedeemer;\n\n  // Scaling factor to account for differences in decimals between OUSG/rOUSG and BUIDL/USDC\n  uint256 public immutable decimalsMultiplier;\n\n  // The address that receives USDC for subscriptions\n  address public usdcReceiver;\n\n  // Address of the oracle that provides the `ousgPrice`\n  IRWAOracle public oracle;\n\n  // The address in which USDC should be sent to as a fee for minting and redeeming\n  address public feeReceiver;\n\n  // Fee collected when minting OUSG (in basis points)\n  uint256 public mintFee;\n\n  // Fee collected when redeeming OUSG (in basis points)\n  uint256 public redeemFee;\n\n  // Minimum amount of USDC that must be deposited to mint OUSG or rOUSG\n  // Denoted in 6 decimals for USDC\n  uint256 public minimumDepositAmount = 100_000e6;\n\n  // Minimum amount of USDC that must be redeemed for to redeem OUSG or rOUSG\n  // Denoted in 6 decimals for USDC\n  uint256 public minimumRedemptionAmount = 49_999e6;\n\n  // Whether minting is paused for this contract\n  bool public mintPaused;\n\n  // Whether redemptions are paused for this contract\n  bool public redeemPaused;\n\n  // The minimum amount of BUIDL that must be redeemed in a single redemption\n  // with the BUIDLRedeemer contract\n  uint256 public minBUIDLRedeemAmount = 250_000e6;\n\n  // Chainlink USDC Price Oracle\n  AggregatorV3Interface public priceFeedUSDCUSD =\n    AggregatorV3Interface(0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6);\n\n  // Optional investor-based rate limiting contract reference\n  IInvestorBasedRateLimiter public investorBasedRateLimiter;\n\n  /**\n   * @notice Constructor.\n   *\n   * @param defaultAdmin        Address that receives all roles during init DEFAULT_ADMIN_ROLE\n   * @param _usdc               USDC's token contract address\n   * @param _usdcReciever       Address that receives USDC during minting\n   * @param _feeReceiver        Address that receives mint and redemption fees\n   * @param _ousgOracle         OUSG's oracle contract address\n   * @param _ousg               OUSG's token contract address\n   * @param _rousg              rOUSG's token contract address\n   * @param _buidl              BUIDL token contract address\n   * @param _buidlRedeemer      Contract address used for instant redemptions of BUIDL\n   * @param rateLimiterConfig   See IOUSGInstantManager.sol & InstantMintTimeBasedRateLimiter.sol\n   *\n   * @dev We calculate `decimalsMultiplier` by subtracting OUSG's decimals by\n   *      the `usdc` contract's decimals and performing 10 ^ difference.\n   *      Deployment will fail if the difference is a negative number via\n   *      runtime underflow protections provided by our solidity version.\n   */\n  constructor(\n    address defaultAdmin,\n    address _usdc,\n    address _usdcReciever,\n    address _feeReceiver,\n    address _ousgOracle,\n    address _ousg,\n    address _rousg,\n    address _buidl,\n    address _buidlRedeemer,\n    RateLimiterConfig memory rateLimiterConfig\n  )\n    InstantMintTimeBasedRateLimiter(\n      rateLimiterConfig.mintLimitDuration,\n      rateLimiterConfig.redeemLimitDuration,\n      rateLimiterConfig.mintLimit,\n      rateLimiterConfig.redeemLimit\n    )\n  {\n    require(\n      address(_usdc) != address(0),\n      \"OUSGInstantManager: USDC cannot be 0x0\"\n    );\n    require(\n      address(_usdcReciever) != address(0),\n      \"OUSGInstantManager: USDC Receiver cannot be 0x0\"\n    );\n    require(\n      address(_feeReceiver) != address(0),\n      \"OUSGInstantManager: feeReceiver cannot be 0x0\"\n    );\n    require(\n      address(_ousgOracle) != address(0),\n      \"OUSGInstantManager: OUSG Oracle cannot be 0x0\"\n    );\n    require(_ousg != address(0), \"OUSGInstantManager: OUSG cannot be 0x0\");\n    require(_rousg != address(0), \"OUSGInstantManager: rOUSG cannot be 0x0\");\n    require(_buidl != address(0), \"OUSGInstantManager: BUIDL cannot be 0x0\");\n    require(\n      address(_buidlRedeemer) != address(0),\n      \"OUSGInstantManager: BUIDL Redeemer cannot be 0x0\"\n    );\n    require(\n      IERC20Metadata(_ousg).decimals() == IERC20Metadata(_rousg).decimals(),\n      \"OUSGInstantManager: OUSG decimals must be equal to rOUSG decimals\"\n    );\n    require(\n      IERC20Metadata(_usdc).decimals() == IERC20Metadata(_buidl).decimals(),\n      \"OUSGInstantManager: USDC decimals must be equal to BUIDL decimals\"\n    );\n    require(\n      priceFeedUSDCUSD.decimals() == 8,\n      \"OUSGInstantManager::Invalid oracle decimals\"\n    );\n\n    usdc = IERC20(_usdc);\n    usdcReceiver = _usdcReciever;\n    feeReceiver = _feeReceiver;\n    oracle = IRWAOracle(_ousgOracle);\n    ousg = IRWALike(_ousg);\n    rousg = ROUSG(_rousg);\n    buidl = IERC20(_buidl);\n    buidlRedeemer = IRedemption(_buidlRedeemer);\n    decimalsMultiplier =\n      10 **\n        (IERC20Metadata(_ousg).decimals() - IERC20Metadata(_usdc).decimals());\n    require(\n      OUSG_TO_ROUSG_SHARES_MULTIPLIER ==\n        rousg.OUSG_TO_ROUSG_SHARES_MULTIPLIER(),\n      \"OUSGInstantManager: OUSG to rOUSG shares multiplier must be equal to rOUSG's\"\n    );\n\n    _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);\n    _grantRole(CONFIGURER_ROLE, defaultAdmin);\n    _grantRole(PAUSER_ROLE, defaultAdmin);\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                            Mint/Redeem\n  //////////////////////////////////////////////////////////////*/\n  /**\n   * @notice Calculates fees and triggers minting OUSG for a given amount of USDC\n   *\n   * @dev Please note that the fees are accumulated in `feeReceiver`\n   *\n   * @param usdcAmountIn amount of USDC exchanged for OUSG (in whatever decimals\n   *                     specifed by usdc token contract)\n   *\n   * @return ousgAmountOut The quantity of OUSG minted for the user\n   *                       (18 decimals per OUSG contract)\n   */\n  function mint(\n    uint256 usdcAmountIn\n  )\n    external\n    override\n    nonReentrant\n    whenMintNotPaused\n    returns (uint256 ousgAmountOut)\n  {\n    ousgAmountOut = _mint(usdcAmountIn, msg.sender);\n    emit InstantMintOUSG(msg.sender, usdcAmountIn, ousgAmountOut);\n  }\n\n  /**\n   * @notice Calculates fees and triggers minting rOUSG for a given amount of USDC\n   *\n   * @dev Please note that the fees are accumulated in `feeReceiver`\n   *\n   * @param usdcAmountIn amount of USDC exchanged for rOUSG (in whatever decimals\n   *                     specifed by usdc token contract)\n   *\n   * @return rousgAmountOut The quantity of rOUSG minted for the user\n   *                        (18 decimals per rOUSG contract)\n   */\n  function mintRebasingOUSG(\n    uint256 usdcAmountIn\n  )\n    external\n    override\n    nonReentrant\n    whenMintNotPaused\n    returns (uint256 rousgAmountOut)\n  {\n    uint256 ousgAmountOut = _mint(usdcAmountIn, address(this));\n    ousg.approve(address(rousg), ousgAmountOut);\n    rousg.wrap(ousgAmountOut);\n    rousgAmountOut = rousg.transferShares(\n      msg.sender,\n      ousgAmountOut * OUSG_TO_ROUSG_SHARES_MULTIPLIER\n    );\n\n    emit InstantMintRebasingOUSG(\n      msg.sender,\n      usdcAmountIn,\n      ousgAmountOut,\n      rousgAmountOut\n    );\n  }\n\n  function _mint(\n    uint256 usdcAmountIn,\n    address to\n  ) internal returns (uint256 ousgAmountOut) {\n    require(\n      IERC20Metadata(address(usdc)).decimals() == 6,\n      \"OUSGInstantManager::_mint: USDC decimals must be 6\"\n    );\n    _assertUSDCPrice();\n    require(\n      usdcAmountIn >= minimumDepositAmount,\n      \"OUSGInstantManager::_mint: Deposit amount too small\"\n    );\n    _checkAndUpdateInstantMintLimit(usdcAmountIn);\n    if (address(investorBasedRateLimiter) != address(0)) {\n      investorBasedRateLimiter.checkAndUpdateMintLimit(\n        msg.sender,\n        usdcAmountIn\n      );\n    }\n\n    require(\n      usdc.allowance(msg.sender, address(this)) >= usdcAmountIn,\n      \"OUSGInstantManager::_mint: Allowance must be given to OUSGInstantManager\"\n    );\n\n    uint256 usdcFees = _getInstantMintFees(usdcAmountIn);\n    uint256 usdcAmountAfterFee = usdcAmountIn - usdcFees;\n\n    // Calculate the mint amount based on mint fees and usdc quantity\n    uint256 ousgPrice = getOUSGPrice();\n    ousgAmountOut = _getMintAmount(usdcAmountAfterFee, ousgPrice);\n\n    // Transfer USDC\n    if (usdcFees > 0) {\n      usdc.transferFrom(msg.sender, feeReceiver, usdcFees);\n    }\n    usdc.transferFrom(msg.sender, usdcReceiver, usdcAmountAfterFee);\n\n    emit MintFeesDeducted(msg.sender, feeReceiver, usdcFees, usdcAmountIn);\n\n    ousg.mint(to, ousgAmountOut);\n  }\n\n  /**\n   * @notice Calculates fees and triggers a redemption of OUSG for a given amount of USDC\n   *\n   * @dev Please note that the fees are accumulated in `feeReceiver`\n   *\n   * @param ousgAmountIn Amount of OUSG to redeem\n   *\n   * @return usdcAmountOut The amount of USDC returned to the user\n   */\n  function redeem(\n    uint256 ousgAmountIn\n  )\n    external\n    override\n    nonReentrant\n    whenRedeemNotPaused\n    returns (uint256 usdcAmountOut)\n  {\n    require(\n      ousg.allowance(msg.sender, address(this)) >= ousgAmountIn,\n      \"OUSGInstantManager::redeem: Insufficient allowance\"\n    );\n    ousg.transferFrom(msg.sender, address(this), ousgAmountIn);\n    usdcAmountOut = _redeem(ousgAmountIn);\n    emit InstantRedemptionOUSG(msg.sender, ousgAmountIn, usdcAmountOut);\n  }\n\n  /**\n   * @notice Calculates fees and triggers minting rOUSG for a given amount of USDC\n   *\n   * @dev Please note that the fees are actually accumulated in `feeReceiver`\n   *\n   * @param rousgAmountIn Amount of rOUSG to redeem\n   *\n   * @return usdcAmountOut The amount of USDC returned to the user\n   */\n  function redeemRebasingOUSG(\n    uint256 rousgAmountIn\n  )\n    external\n    override\n    nonReentrant\n    whenRedeemNotPaused\n    returns (uint256 usdcAmountOut)\n  {\n    require(\n      rousg.allowance(msg.sender, address(this)) >= rousgAmountIn,\n      \"OUSGInstantManager::redeemRebasingOUSG: Insufficient allowance\"\n    );\n    rousg.transferFrom(msg.sender, address(this), rousgAmountIn);\n    rousg.unwrap(rousgAmountIn);\n    uint256 ousgAmountIn = rousg.getSharesByROUSG(rousgAmountIn) /\n      OUSG_TO_ROUSG_SHARES_MULTIPLIER;\n    usdcAmountOut = _redeem(ousgAmountIn);\n    emit InstantRedemptionRebasingOUSG(\n      msg.sender,\n      rousgAmountIn,\n      ousgAmountIn,\n      usdcAmountOut\n    );\n  }\n\n  function _redeem(\n    uint256 ousgAmountIn\n  ) internal returns (uint256 usdcAmountOut) {\n    require(\n      IERC20Metadata(address(usdc)).decimals() == 6,\n      \"OUSGInstantManager::_redeem: USDC decimals must be 6\"\n    );\n    require(\n      IERC20Metadata(address(buidl)).decimals() == 6,\n      \"OUSGInstantManager::_redeem: BUIDL decimals must be 6\"\n    );\n    _assertUSDCPrice();\n    uint256 ousgPrice = getOUSGPrice();\n    uint256 usdcAmountToRedeem = _getRedemptionAmount(ousgAmountIn, ousgPrice);\n\n    require(\n      usdcAmountToRedeem >= minimumRedemptionAmount,\n      \"OUSGInstantManager::_redeem: Redemption amount too small\"\n    );\n    _checkAndUpdateInstantRedemptionLimit(usdcAmountToRedeem);\n\n    if (address(investorBasedRateLimiter) != address(0)) {\n      investorBasedRateLimiter.checkAndUpdateRedemptionLimit(\n        msg.sender,\n        usdcAmountToRedeem\n      );\n    }\n\n    uint256 usdcFees = _getInstantRedemptionFees(usdcAmountToRedeem);\n    usdcAmountOut = usdcAmountToRedeem - usdcFees;\n\n    ousg.burn(ousgAmountIn);\n\n    uint256 usdcBalance = usdc.balanceOf(address(this));\n    if (usdcAmountToRedeem <= usdcBalance) {\n      // There is enough USDC in the contract to cover the redemption and fees,\n      // use it without redeeming more BUIDL.\n      emit BUIDLRedemptionSkipped(\n        msg.sender,\n        usdcAmountToRedeem,\n        usdcBalance - usdcAmountToRedeem\n      );\n    } else if (usdcAmountToRedeem - usdcBalance >= minBUIDLRedeemAmount) {\n      // The amount of additional USDC needed in this contract is over minBUIDLRedeemAmount,\n      // do a BUIDL redemption to cover the difference.\n      _redeemBUIDL(usdcAmountToRedeem - usdcBalance);\n    } else {\n      // There isn't enough USDC held by this contract to cover the redemption,\n      // so we perform a BUIDL redemption of BUIDL's minimum required amount.\n      // The remaining amount of USDC will be held in the contract for future redemptions.\n      _redeemBUIDL(minBUIDLRedeemAmount);\n      emit MinimumBUIDLRedemption(\n        msg.sender,\n        minBUIDLRedeemAmount,\n        usdcBalance + minBUIDLRedeemAmount - usdcAmountToRedeem\n      );\n    }\n\n    if (usdcFees > 0) {\n      usdc.transfer(feeReceiver, usdcFees);\n    }\n    emit RedeemFeesDeducted(msg.sender, feeReceiver, usdcFees, usdcAmountOut);\n\n    usdc.transfer(msg.sender, usdcAmountOut);\n  }\n\n  function _redeemBUIDL(uint256 buidlAmountToRedeem) internal {\n    require(\n      buidl.balanceOf(address(this)) >= buidlAmountToRedeem,\n      \"OUSGInstantManager::_redeemBUIDL: Insufficient BUIDL balance\"\n    );\n    uint256 usdcBalanceBefore = usdc.balanceOf(address(this));\n    buidl.approve(address(buidlRedeemer), buidlAmountToRedeem);\n    buidlRedeemer.redeem(buidlAmountToRedeem);\n    require(\n      usdc.balanceOf(address(this)) == usdcBalanceBefore + buidlAmountToRedeem,\n      \"OUSGInstantManager::_redeemBUIDL: BUIDL:USDC not 1:1\"\n    );\n  }\n\n  /**\n   * @notice Returns the current price of OUSG in USDC\n   *\n   * @dev Sanity check: this function will revert if the price is unexpectedly low\n   *\n   * @return price The current price of OUSG in USDC\n   */\n  function getOUSGPrice() public view returns (uint256 price) {\n    (price, ) = oracle.getPriceData();\n    require(\n      price >= MINIMUM_OUSG_PRICE,\n      \"OUSGInstantManager::getOUSGPrice: Price unexpectedly low\"\n    );\n  }\n\n  function _assertUSDCPrice() internal view {\n    (, int price, , uint256 updatedAt, ) = priceFeedUSDCUSD.latestRoundData();\n    require(\n      updatedAt >= block.timestamp - 1 days - 6 hours,\n      \"OUSGInstantManager::_assertUSDCPrice: Price outdated\"\n    );\n\n    // price of USDC must be recent and greater than MINIMUM_USDC_PRICE at all times.\n    require(\n      price >= MINIMUM_USDC_PRICE,\n      \"OUSGInstantManager::_assertUSDCPrice: USDC price too low\"\n    );\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                    Rate Limiter Configuration\n  //////////////////////////////////////////////////////////////*/\n  /**\n   * @notice Set the mintLimit constraint inside the InstantMintTimeBasedRateLimiter\n   *         base contract\n   *\n   * @param _instantMintLimit New limit that dicates how much USDC can be transfered\n   *                     for minting in a specified duration\n   *                     (in 6 decimals per the USDC contract)\n   */\n  function setInstantMintLimit(\n    uint256 _instantMintLimit\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    _setInstantMintLimit(_instantMintLimit);\n  }\n\n  /**\n   * @notice Set the redeemLimit constraint inside the InstantMintTimeBasedRateLimiter\n   *         base contract\n   *\n   * @param _instantRedemptionLimit New limit that dicates how much USDC\n   *                       can be redeemed in a specified duration\n   *                       (in 6 decimals per the USDC contract)\n   */\n  function setInstantRedemptionLimit(\n    uint256 _instantRedemptionLimit\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    _setInstantRedemptionLimit(_instantRedemptionLimit);\n  }\n\n  /**\n   * @notice Sets mintLimitDuration constraint inside the InstantMintTimeBasedRateLimiter\n   *         base contract\n   *\n   * @param _instantMintLimitDuration New limit that specifies the interval\n   *                             (in seconds) in which only `mintLimit` USDC\n   *                             can be used for minting within\n   */\n  function setInstantMintLimitDuration(\n    uint256 _instantMintLimitDuration\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    _setInstantMintLimitDuration(_instantMintLimitDuration);\n  }\n\n  /**\n   * @notice Sets redeemLimitDuration inside the InstantMintTimeBasedRateLimiter\n   *         base contract\n   *\n   * @param _instantRedemptionLimitDuration New limit that specifies the interval\n   *                               (in seconds) in which only `redeemLimit` USDC\n   *                               can be redeemed within\n   */\n  function setInstantRedemptionLimitDuration(\n    uint256 _instantRedemptionLimitDuration\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    _setInstantRedemptionLimitDuration(_instantRedemptionLimitDuration);\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                    Mint/Redeem Configuration\n  //////////////////////////////////////////////////////////////*/\n  /**\n   * @notice Sets the mint fee\n   *\n   * @param _mintFee new mint fee specified in basis points\n   */\n  function setMintFee(\n    uint256 _mintFee\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    require(_mintFee < 200, \"OUSGInstantManager::setMintFee: Fee too high\");\n    emit MintFeeSet(mintFee, _mintFee);\n    mintFee = _mintFee;\n  }\n\n  /**\n   * @notice Sets the redeem fee.\n   *\n   * @param _redeemFee new redeem fee specified in basis points\n   */\n  function setRedeemFee(\n    uint256 _redeemFee\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    require(_redeemFee < 200, \"OUSGInstantManager::setRedeemFee: Fee too high\");\n    emit RedeemFeeSet(redeemFee, _redeemFee);\n    redeemFee = _redeemFee;\n  }\n\n  /**\n   * @notice Admin function to set the minimum amount required for a deposit\n   *\n   * @param _minimumDepositAmount The minimum amount required to submit a deposit\n   *                          request\n   */\n  function setMinimumDepositAmount(\n    uint256 _minimumDepositAmount\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    require(\n      _minimumDepositAmount >= FEE_GRANULARITY,\n      \"OUSGInstantManager::setMinimumDepositAmount: Amount too small\"\n    );\n\n    emit MinimumDepositAmountSet(minimumDepositAmount, _minimumDepositAmount);\n    minimumDepositAmount = _minimumDepositAmount;\n  }\n\n  /**\n   * @notice Admin function to set the minimum amount to redeem\n   *\n   * @param _minimumRedemptionAmount The minimum amount required to submit a\n   *                                 redemption request\n   */\n  function setMinimumRedemptionAmount(\n    uint256 _minimumRedemptionAmount\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    require(\n      _minimumRedemptionAmount >= FEE_GRANULARITY,\n      \"OUSGInstantManager::setMinimumRedemptionAmount: Amount too small\"\n    );\n    emit MinimumRedemptionAmountSet(\n      minimumRedemptionAmount,\n      _minimumRedemptionAmount\n    );\n    minimumRedemptionAmount = _minimumRedemptionAmount;\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                    General Configuration\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Admin function to set the USDC receiver\n   *\n   * @param _usdcReceiver The new USDC receiver\n   */\n  function setUsdcReceiver(\n    address _usdcReceiver\n  ) external override onlyRole(DEFAULT_ADMIN_ROLE) {\n    require(\n      _usdcReceiver != address(0),\n      \"OUSGInstantManager::setUsdcReceiver: USDC receiver cannot be 0x0\"\n    );\n    emit UsdcReceiverSet(usdcReceiver, _usdcReceiver);\n    usdcReceiver = _usdcReceiver;\n  }\n\n  /**\n   * @notice Admin function to set the minimum amount required to redeem BUIDL\n   *\n   * @param _minimumBUIDLRedemptionAmount The minimum amount required to redeem BUIDL\n   */\n  function setMinimumBUIDLRedemptionAmount(\n    uint256 _minimumBUIDLRedemptionAmount\n  ) external override onlyRole(DEFAULT_ADMIN_ROLE) {\n    emit MinimumBUIDLRedemptionAmountSet(\n      minBUIDLRedeemAmount,\n      _minimumBUIDLRedemptionAmount\n    );\n    minBUIDLRedeemAmount = _minimumBUIDLRedemptionAmount;\n  }\n\n  /**\n   * @notice Admin function to set the oracle address\n   *\n   * @param _oracle The address of the oracle that provides the OUSG price\n   *                in USDC\n   */\n  function setOracle(\n    address _oracle\n  ) external override onlyRole(DEFAULT_ADMIN_ROLE) {\n    require(\n      _oracle != address(0),\n      \"OUSGInstantManager::setOracle: Oracle cannot be 0x0\"\n    );\n    emit OracleSet(address(oracle), _oracle);\n    oracle = IRWAOracle(_oracle);\n  }\n\n  /**\n   * @notice Admin function to set the USDC/USD oracle address\n   *\n   * @param _priceFeedUSDCUSD The address of the oracle that provides the USDC price\n   *                          in USD with 8 decimals\n   */\n  function setUSDCOracle(\n    address _priceFeedUSDCUSD\n  ) external override onlyRole(DEFAULT_ADMIN_ROLE) {\n    require(\n      _priceFeedUSDCUSD != address(0),\n      \"OUSGInstantManager::setUSDCOracle: Oracle cannot be 0x0\"\n    );\n    emit USDCOracleSet(address(priceFeedUSDCUSD), _priceFeedUSDCUSD);\n    priceFeedUSDCUSD = AggregatorV3Interface(_priceFeedUSDCUSD);\n    require(\n      priceFeedUSDCUSD.decimals() == 8,\n      \"OUSGInstantManager::setUSDCOracle: Invalid oracle decimals\"\n    );\n    _assertUSDCPrice();\n  }\n\n  /**\n   * @notice Admin function to set the fee receiver address\n\n   * @param _feeReceiver The address to receive the mint and redemption fees\n   */\n  function setFeeReceiver(\n    address _feeReceiver\n  ) external override onlyRole(DEFAULT_ADMIN_ROLE) {\n    require(\n      _feeReceiver != address(0),\n      \"OUSGInstantManager::setFeeReceiver: FeeReceiver cannot be 0x0\"\n    );\n    emit FeeReceiverSet(feeReceiver, _feeReceiver);\n    feeReceiver = _feeReceiver;\n  }\n\n  /**\n   * @notice Admin function to set the optional investor-based rate limiter\n   *\n   * @param _investorBasedRateLimiter The address of the investor-based rate limiter contract\n   */\n  function setInvestorBasedRateLimiter(\n    address _investorBasedRateLimiter\n  ) external override onlyRole(DEFAULT_ADMIN_ROLE) {\n    emit InvestorBasedRateLimiterSet(\n      address(investorBasedRateLimiter),\n      _investorBasedRateLimiter\n    );\n    investorBasedRateLimiter = IInvestorBasedRateLimiter(\n      _investorBasedRateLimiter\n    );\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                  Helper fee conversion functions\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Given a deposit amount and a price, returns the OUSG amount due\n   *\n   * @param usdcAmountIn The amount deposited in units of USDC\n   * @param price        The price at which to mint\n   */\n  function _getMintAmount(\n    uint256 usdcAmountIn,\n    uint256 price\n  ) internal view returns (uint256 ousgAmountOut) {\n    uint256 amountE36 = _scaleUp(usdcAmountIn) * 1e18;\n    ousgAmountOut = amountE36 / price;\n  }\n\n  /**\n   * @notice Given a redemption amount and a price, returns the USDC amount due\n   *\n   * @param ousgAmountBurned The amount of OUSG burned for a redemption\n   * @param price            The price at which to redeem\n   */\n  function _getRedemptionAmount(\n    uint256 ousgAmountBurned,\n    uint256 price\n  ) internal view returns (uint256 usdcOwed) {\n    uint256 amountE36 = ousgAmountBurned * price;\n    usdcOwed = _scaleDown(amountE36 / 1e18);\n  }\n\n  /**\n   * @notice Given amount of USDC, returns how much in fees are owed\n   *\n   * @param usdcAmount Amount of USDC to calculate fees\n   *                   (in 6 decimals)\n   */\n  function _getInstantMintFees(\n    uint256 usdcAmount\n  ) internal view returns (uint256) {\n    return (usdcAmount * mintFee) / FEE_GRANULARITY;\n  }\n\n  /**\n   * @notice Given amount of USDC, returns how much in fees are owed\n   *\n   * @param usdcAmount Amount USDC to calculate fees\n   *                   (in decimals of USDC)\n   */\n  function _getInstantRedemptionFees(\n    uint256 usdcAmount\n  ) internal view returns (uint256) {\n    return (usdcAmount * redeemFee) / FEE_GRANULARITY;\n  }\n\n  /**\n   * @notice Scale provided amount up by `decimalsMultiplier`\n   *\n   * @dev This helper is used for converting a USDC amount's decimals\n   *      representation to the rOUSG/OUSG decimals representation.\n   */\n  function _scaleUp(uint256 amount) internal view returns (uint256) {\n    return amount * decimalsMultiplier;\n  }\n\n  /**\n   * @notice Scale provided amount down by `decimalsMultiplier`\n   *\n   * @dev This helper is used for converting an rOUSG/OUSG amount's decimals\n   *      representation to the USDC decimals representation.\n   */\n  function _scaleDown(uint256 amount) internal view returns (uint256) {\n    return amount / decimalsMultiplier;\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                          Pause/Unpause\n  //////////////////////////////////////////////////////////////*/\n\n  /// @notice Ensure that the mint functionality is not paused\n  modifier whenMintNotPaused() {\n    require(!mintPaused, \"OUSGInstantManager: Mint paused\");\n    _;\n  }\n\n  /// @notice Ensure that the redeem functionality is not paused\n  modifier whenRedeemNotPaused() {\n    require(!redeemPaused, \"OUSGInstantManager: Redeem paused\");\n    _;\n  }\n\n  /// @notice Pause the mint functionality\n  function pauseMint() external onlyRole(PAUSER_ROLE) {\n    mintPaused = true;\n    emit MintPaused();\n  }\n\n  /// @notice Unpause the mint functionality\n  function unpauseMint() external onlyRole(DEFAULT_ADMIN_ROLE) {\n    mintPaused = false;\n    emit MintUnpaused();\n  }\n\n  /// @notice Pause the redeem functionality\n  function pauseRedeem() external onlyRole(PAUSER_ROLE) {\n    redeemPaused = true;\n    emit RedeemPaused();\n  }\n\n  /// @notice Unpause the redeem functionality\n  function unpauseRedeem() external onlyRole(DEFAULT_ADMIN_ROLE) {\n    redeemPaused = false;\n    emit RedeemUnpaused();\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                          Miscellaneous\n  //////////////////////////////////////////////////////////////*/\n  function multiexcall(\n    ExCallData[] calldata exCallData\n  )\n    external\n    payable\n    override\n    onlyRole(DEFAULT_ADMIN_ROLE)\n    returns (bytes[] memory results)\n  {\n    results = new bytes[](exCallData.length);\n    for (uint256 i; i < exCallData.length; ++i) {\n      (bool success, bytes memory ret) = address(exCallData[i].target).call{\n        value: exCallData[i].value\n      }(exCallData[i].data);\n      require(success, \"Call Failed\");\n      results[i] = ret;\n    }\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(RETRIEVER_ROLE) {\n    IERC20(token).transfer(to, amount);\n  }\n}\n"
      },
      "contracts/InstantMintTimeBasedRateLimiter.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\n/**\n * @title InstantMintTimeBasedRateLimiter\n *\n * @notice This abstract contract implements two rate limiters: one for minting\n *         and one for redeeming. Each limit is completely independent: mints\n *         and redemption don't offset each other. Each limit is associated\n *         with a duration, after which the tracked amount is reset. The\n *         amounts tracked are agnostic to a specific token; the usage is\n *         determined by the inheriting contracts.\n *\n * @dev Although this contract has all of its functions implemented, this\n *      contract is marked abstract to prevent an accidental deployment and to\n *      signify that we would never deploy this contract standalone.\n *\n */\nabstract contract InstantMintTimeBasedRateLimiter {\n  // `currentInstantMintAmount` resets after this interval (in seconds)\n  uint256 public resetInstantMintDuration;\n  // timestamp when `currentInstantMintAmount` was last reset\n  uint256 public lastResetInstantMintTime;\n\n  // maximum amount that can be minted during a `resetInstantMintDuration` window\n  uint256 public instantMintLimit;\n  // amount already minted during the current `resetInstantMintDuration` window\n  uint256 public currentInstantMintAmount;\n\n  // `currentInstantRedemptionAmount` resets after this interval (in seconds)\n  uint256 public resetInstantRedemptionDuration;\n  // timestamp when the `currentInstantRedemptionAmount` was last reset\n  uint256 public lastResetInstantRedemptionTime;\n\n  // maximum amount that can be redeemed during a `resetInstantRedemptionDuration` window\n  uint256 public instantRedemptionLimit;\n  // amount already redeemed during the current `resetInstantRedemptionDuration` window\n  uint256 public currentInstantRedemptionAmount;\n\n  /**\n   * @notice In the constructor, we initialize the variables for the mint and\n   *         redemption rate limiters.\n   *\n   * @param _instantMintResetDuration   `currentInstantMintAmount` resets after this interval\n   *                                    (in seconds)\n   * @param _instantRedemptionResetDuration `currentInstantRedemptionAmount` resets after this\n   *                                    interval (in seconds)\n   * @param _instantMintLimit           maximum amount that can be minted during a\n   *                                    `resetInstantMintDuration` window\n   * @param _instantRedemptionLimit     maximum amount that can be redeemed during a\n   *                                    `resetInstantRedemptionDuration` window\n   *\n   * @dev If a duration is zero, the limit resets before each mint/redemption.\n   * @dev If a limit is zero, the relevant check always fails.\n   */\n  constructor(\n    uint256 _instantMintResetDuration,\n    uint256 _instantRedemptionResetDuration,\n    uint256 _instantMintLimit,\n    uint256 _instantRedemptionLimit\n  ) {\n    resetInstantMintDuration = _instantMintResetDuration;\n    resetInstantRedemptionDuration = _instantRedemptionResetDuration;\n    instantMintLimit = _instantMintLimit; // can be zero to disable minting\n    instantRedemptionLimit = _instantRedemptionLimit; // can be zero to disable redemptions\n\n    lastResetInstantMintTime = block.timestamp;\n    lastResetInstantRedemptionTime = block.timestamp;\n  }\n\n  /**\n   * @notice Checks the requested mint amount against the rate limiter (and\n   *         updates the remaining amount)\n   *\n   * @param amount The requested mint amount\n   *\n   * @dev Reverts if the requested mint amount exceeds the current limit\n   */\n  function _checkAndUpdateInstantMintLimit(uint256 amount) internal {\n    require(amount > 0, \"RateLimit: mint amount can't be zero\");\n\n    if (\n      block.timestamp >= lastResetInstantMintTime + resetInstantMintDuration\n    ) {\n      // time has passed, reset\n      currentInstantMintAmount = 0;\n      lastResetInstantMintTime = block.timestamp;\n    }\n    require(\n      currentInstantMintAmount + amount <= instantMintLimit,\n      \"RateLimit: Mint exceeds rate limit\"\n    );\n\n    currentInstantMintAmount += amount;\n  }\n\n  /**\n   * @notice Checks the requested redemption amount against the rate limiter\n   *         (and updates the remaining amount)\n   *\n   * @param amount The requested redemption amount\n   *\n   * @dev Reverts if the requested redemption amount exceeds the current\n   *      limit\n   */\n  function _checkAndUpdateInstantRedemptionLimit(uint256 amount) internal {\n    require(amount > 0, \"RateLimit: redemption amount can't be zero\");\n\n    if (\n      block.timestamp >=\n      lastResetInstantRedemptionTime + resetInstantRedemptionDuration\n    ) {\n      // time has passed, reset\n      currentInstantRedemptionAmount = 0;\n      lastResetInstantRedemptionTime = block.timestamp;\n    }\n    require(\n      currentInstantRedemptionAmount + amount <= instantRedemptionLimit,\n      \"RateLimit: Redemption exceeds rate limit\"\n    );\n    currentInstantRedemptionAmount += amount;\n  }\n\n  /**\n   * @notice Update the amount of token that can be minted during one duration\n   *\n   * @param _instantMintLimit The token amount\n   *\n   * @dev If a limit is zero, the relevant check always fails.\n   */\n  function _setInstantMintLimit(uint256 _instantMintLimit) internal {\n    instantMintLimit = _instantMintLimit;\n    emit InstantMintLimitSet(_instantMintLimit);\n  }\n\n  /**\n   * @notice Update the amount of token that can be redeemed during one duration\n   *\n   * @param _redemptionLimit The token amount\n   *\n   * @dev If a limit is zero, the relevant check always fails.\n   */\n  function _setInstantRedemptionLimit(uint256 _redemptionLimit) internal {\n    instantRedemptionLimit = _redemptionLimit;\n    emit InstantRedemptionLimitSet(_redemptionLimit);\n  }\n\n  /**\n   * @notice Update the duration for the mint rate limiter\n   *\n   * @param _instantMintResetDuration The duration in seconds\n   *\n   * @dev If a duration is zero, the limit resets before each mint/redemption\n   */\n  function _setInstantMintLimitDuration(\n    uint256 _instantMintResetDuration\n  ) internal {\n    resetInstantMintDuration = _instantMintResetDuration;\n    emit InstantMintLimitDurationSet(_instantMintResetDuration);\n  }\n\n  /**\n   * @notice Update the duration for the redemption rate limiter\n   *\n   * @param _instantRedemptionResetDuration The duration in seconds\n   *\n   * @dev If a duration is zero, the limit resets before each mint/redemption\n   */\n  function _setInstantRedemptionLimitDuration(\n    uint256 _instantRedemptionResetDuration\n  ) internal {\n    resetInstantRedemptionDuration = _instantRedemptionResetDuration;\n    emit InstantRedemptionLimitDurationSet(_instantRedemptionResetDuration);\n  }\n\n  /**\n   * @notice Event emitted when instant mint limit is set\n   *\n   * @param instantMintLimit How much of some token can be minted within\n   *                  an interval of length `resetInstantMintDuration`\n   *\n   * @dev See inheriting contract for representation\n   */\n  event InstantMintLimitSet(uint256 instantMintLimit);\n\n  /**\n   * @notice Event emitted when instant redemption limit is set\n   *\n   * @param instantRedemptionLimit How much of some token can be redeemed within\n   *                    an interval of length `resetInstantRedemptionDuration`\n   *\n   * @dev See inheriting contract for representation\n   */\n  event InstantRedemptionLimitSet(uint256 instantRedemptionLimit);\n\n  /**\n   * @notice Event emitted when mint limit duration is set\n   *\n   * @param instantMintLimitDuration The time window in which `instantMintLimit`\n   *                          of some token can be minted\n   *\n   * @dev instantMintLimitDuration is specified in seconds\n   */\n  event InstantMintLimitDurationSet(uint256 instantMintLimitDuration);\n\n  /**\n   * @notice Event emitted when redemption limit duration is set\n   *\n   * @param redemptionLimitDuration The time window in which `instantRedemptionLimit`\n   *                            of some token can be redeemed\n   *\n   * @dev redemptionLimitDuration is specified in seconds.\n   */\n  event InstantRedemptionLimitDurationSet(uint256 redemptionLimitDuration);\n}\n"
      },
      "contracts/interfaces/IRWALike.sol": {
        "content": "/**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"
      },
      "contracts/ousg/rOUSG.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/external/openzeppelin/contracts/token/IERC20.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/token/ERC20/IERC20MetadataUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol\";\nimport \"contracts/kyc/KYCRegistryClientUpgradeable.sol\";\nimport \"contracts/rwaOracles/IRWAOracle.sol\";\n\n/**\n * @title Interest-bearing ERC20-like token for OUSG.\n *\n * rOUSG balances are dynamic and represent the holder's share of the underlying OUSG\n * controlled by the protocol. To calculate each account's balance, we do\n *\n *   shares[account] * ousgPrice\n *\n * For example, if we assume that we have the following:\n *\n *   ousgPrice = 105 (18 decimals)\n *   rousg.sharesOf(user1) -> 1 (22 decimals)\n *   rousg.sharesOf(user2) -> 4 (22 decimals)\n *   ousg.balanceOf(rousg) -> 5 OUSG (18 decimals)\n *\n * Below would be the balances of the users:\n *\n *   rousg.balanceOf(user1) -> 105 rOUSG (18 decimals)\n *   rousg.balanceOf(user2) -> 420 rOUSG (18 decimals)\n *\n * Since balances of all token holders change when the price of OUSG changes, this\n * token cannot fully implement ERC20 standard: it only emits `Transfer` events\n * upon explicit transfer between holders. In contrast, when total amount of pooled\n * Cash increases, no `Transfer` events are generated: doing so would require emitting\n * an event for each token holder and thus running an unbounded loop.\n *\n */\n\ncontract ROUSG is\n  Initializable,\n  ContextUpgradeable,\n  PausableUpgradeable,\n  AccessControlEnumerableUpgradeable,\n  KYCRegistryClientUpgradeable,\n  IERC20Upgradeable,\n  IERC20MetadataUpgradeable\n{\n  /**\n   * @dev rOUSG balances are dynamic and are calculated based on the accounts' shares (OUSG)\n   * and the the price of OUSG. Account shares aren't\n   * normalized, so the contract also stores the sum of all shares to calculate\n   * each account's token balance which equals to:\n   *\n   *   shares[account] * ousgPrice\n   */\n  mapping(address => uint256) private shares;\n\n  /// @dev Allowances are nominated in tokens, not token shares.\n  mapping(address => mapping(address => uint256)) private allowances;\n\n  // Total shares in existence\n  uint256 public totalShares;\n\n  // Address of the oracle that provides the `ousgPrice`\n  IRWAOracle public oracle;\n\n  // Address of the OUSG token\n  IERC20 public ousg;\n\n  // Used to scale up ousg amount -> shares\n  uint256 public constant OUSG_TO_ROUSG_SHARES_MULTIPLIER = 10_000;\n\n  // Name of the token\n  string internal _name;\n\n  // Symbol of the token\n  string internal _symbol;\n\n  // Error when redeeming shares < `OUSG_TO_ROUSG_SHARES_MULTIPLIER`\n  error UnwrapTooSmall();\n\n  // Error when setting the oracle address to zero\n  error CannotSetToZeroAddress();\n\n  /// @dev Role based access control roles\n  bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n  bytes32 public constant BURNER_ROLE = keccak256(\"BURN_ROLE\");\n  bytes32 public constant CONFIGURER_ROLE = keccak256(\"CONFIGURER_ROLE\");\n\n  /// @custom:oz-upgrades-unsafe-allow constructor\n  constructor() {\n    _disableInitializers();\n  }\n\n  function initialize(\n    address _kycRegistry,\n    uint256 requirementGroup,\n    address _ousg,\n    address guardian,\n    address _oracle\n  ) public virtual initializer {\n    __rOUSG_init(_kycRegistry, requirementGroup, _ousg, guardian, _oracle);\n  }\n\n  function __rOUSG_init(\n    address _kycRegistry,\n    uint256 requirementGroup,\n    address _ousg,\n    address guardian,\n    address _oracle\n  ) internal onlyInitializing {\n    __rOUSG_init_unchained(\n      _kycRegistry,\n      requirementGroup,\n      _ousg,\n      guardian,\n      _oracle\n    );\n  }\n\n  function __rOUSG_init_unchained(\n    address _kycRegistry,\n    uint256 _requirementGroup,\n    address _ousg,\n    address guardian,\n    address _oracle\n  ) internal onlyInitializing {\n    __KYCRegistryClientInitializable_init(_kycRegistry, _requirementGroup);\n    ousg = IERC20(_ousg);\n    oracle = IRWAOracle(_oracle);\n    _grantRole(DEFAULT_ADMIN_ROLE, guardian);\n    _grantRole(PAUSER_ROLE, guardian);\n    _grantRole(BURNER_ROLE, guardian);\n    _grantRole(CONFIGURER_ROLE, guardian);\n    _name = \"Rebasing OUSG\";\n    _symbol = \"rOUSG\";\n  }\n\n  /**\n   * @notice Emitted when the name is set\n   *\n   * @param oldName The old name of the token\n   * @param newName The new name of the token\n   */\n  event NameSet(string oldName, string newName);\n\n  /**\n   * @notice Emitted when the symbol is set\n   *\n   * @param oldSymbol The old symbol of the token\n   * @param newSymbol The new symbol of the token\n   */\n\n  event SymbolSet(string oldSymbol, string newSymbol);\n  /**\n   * @notice An executed shares transfer from `sender` to `recipient`.\n   *\n   * @dev emitted in pair with an ERC20-defined `Transfer` event.\n   */\n  event TransferShares(\n    address indexed from,\n    address indexed to,\n    uint256 sharesValue\n  );\n\n  /**\n   * @notice Emitted when the oracle address is set\n   *\n   * @param oldOracle The address of the old oracle\n   * @param newOracle The address of the new oracle\n   */\n  event OracleSet(address indexed oldOracle, address indexed newOracle);\n\n  /**\n   * @return the name of the token.\n   */\n  function name() public view returns (string memory) {\n    return _name;\n  }\n\n  /**\n   * @return the symbol of the token, usually a shorter version of the\n   * name.\n   */\n  function symbol() public view returns (string memory) {\n    return _symbol;\n  }\n\n  /**\n   * @return the number of decimals for getting user representation of a token amount.\n   */\n  function decimals() public pure returns (uint8) {\n    return 18;\n  }\n\n  /**\n   * @return the amount of tokens in existence.\n   */\n  function totalSupply() public view returns (uint256) {\n    return\n      (totalShares * getOUSGPrice()) / (1e18 * OUSG_TO_ROUSG_SHARES_MULTIPLIER);\n  }\n\n  /**\n   * @return the amount of tokens owned by the `_account`.\n   *\n   * @dev Balances are dynamic and equal the `_account`'s OUSG shares multiplied\n   *      by the price of OUSG\n   */\n  function balanceOf(address _account) public view returns (uint256) {\n    return\n      (_sharesOf(_account) * getOUSGPrice()) /\n      (1e18 * OUSG_TO_ROUSG_SHARES_MULTIPLIER);\n  }\n\n  /**\n   * @notice Moves `_amount` tokens from the caller's account to the `_recipient` account.\n   *\n   * @return a boolean value indicating whether the operation succeeded.\n   * Emits a `Transfer` event.\n   * Emits a `TransferShares` event.\n   *\n   * Requirements:\n   *\n   * - `_recipient` cannot be the zero address.\n   * - the caller must have a balance of at least `_amount`.\n   * - the contract must not be paused.\n   *\n   * @dev The `_amount` argument is the amount of tokens, not shares.\n   */\n  function transfer(address _recipient, uint256 _amount) public returns (bool) {\n    _transfer(msg.sender, _recipient, _amount);\n    return true;\n  }\n\n  /**\n   * @return the remaining number of tokens that `_spender` is allowed to spend\n   * on behalf of `_owner` through `transferFrom`. This is zero by default.\n   *\n   * @dev This value changes when `approve` or `transferFrom` is called.\n   */\n  function allowance(\n    address _owner,\n    address _spender\n  ) public view returns (uint256) {\n    return allowances[_owner][_spender];\n  }\n\n  /**\n   * @notice Sets `_amount` as the allowance of `_spender` over the caller's tokens.\n   *\n   * @return a boolean value indicating whether the operation succeeded.\n   * Emits an `Approval` event.\n   *\n   * Requirements:\n   *\n   * - `_spender` cannot be the zero address.\n   * - the contract must not be paused.\n   *\n   * @dev The `_amount` argument is the amount of tokens, not shares.\n   */\n  function approve(address _spender, uint256 _amount) public returns (bool) {\n    _approve(msg.sender, _spender, _amount);\n    return true;\n  }\n\n  /**\n   * @notice Moves `_amount` tokens from `_sender` to `_recipient` using the\n   * allowance mechanism. `_amount` is then deducted from the caller's\n   * allowance.\n   *\n   * @return a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a `Transfer` event.\n   * Emits a `TransferShares` event.\n   * Emits an `Approval` event indicating the updated allowance.\n   *\n   * Requirements:\n   *\n   * - `_sender` and `_recipient` cannot be the zero addresses.\n   * - `_sender` must have a balance of at least `_amount`.\n   * - the caller must have allowance for `_sender`'s tokens of at least `_amount`.\n   * - the contract must not be paused.\n   *\n   * @dev The `_amount` argument is the amount of tokens, not shares.\n   */\n  function transferFrom(\n    address _sender,\n    address _recipient,\n    uint256 _amount\n  ) public returns (bool) {\n    uint256 currentAllowance = allowances[_sender][msg.sender];\n    require(currentAllowance >= _amount, \"TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE\");\n\n    _transfer(_sender, _recipient, _amount);\n    _approve(_sender, msg.sender, currentAllowance - _amount);\n    return true;\n  }\n\n  /**\n   * @notice Atomically increases the allowance granted to `_spender` by the caller by `_addedValue`.\n   *\n   * This is an alternative to `approve` that can be used as a mitigation for\n   * problems described in:\n   * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L42\n   * Emits an `Approval` event indicating the updated allowance.\n   *\n   * Requirements:\n   *\n   * - `_spender` cannot be the the zero address.\n   * - the contract must not be paused.\n   */\n  function increaseAllowance(\n    address _spender,\n    uint256 _addedValue\n  ) public returns (bool) {\n    _approve(\n      msg.sender,\n      _spender,\n      allowances[msg.sender][_spender] + _addedValue\n    );\n    return true;\n  }\n\n  /**\n   * @notice Atomically decreases the allowance granted to `_spender` by the caller by `_subtractedValue`.\n   *\n   * This is an alternative to `approve` that can be used as a mitigation for\n   * problems described in:\n   * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L42\n   * Emits an `Approval` event indicating the updated allowance.\n   *\n   * Requirements:\n   *\n   * - `_spender` cannot be the zero address.\n   * - `_spender` must have allowance for the caller of at least `_subtractedValue`.\n   * - the contract must not be paused.\n   */\n  function decreaseAllowance(\n    address _spender,\n    uint256 _subtractedValue\n  ) public returns (bool) {\n    uint256 currentAllowance = allowances[msg.sender][_spender];\n    require(\n      currentAllowance >= _subtractedValue,\n      \"DECREASED_ALLOWANCE_BELOW_ZERO\"\n    );\n    _approve(msg.sender, _spender, currentAllowance - _subtractedValue);\n    return true;\n  }\n\n  /**\n   * @return the amount of shares owned by `_account`.\n   *\n   * @dev This is the equivalent to the amount of OUSG wrapped by `_account`.\n   */\n  function sharesOf(address _account) public view returns (uint256) {\n    return _sharesOf(_account);\n  }\n\n  /**\n   * @return the amount of shares that corresponds to `_rOUSGAmount` of rOUSG\n   */\n  function getSharesByROUSG(\n    uint256 _rOUSGAmount\n  ) public view returns (uint256) {\n    return\n      (_rOUSGAmount * 1e18 * OUSG_TO_ROUSG_SHARES_MULTIPLIER) / getOUSGPrice();\n  }\n\n  /**\n   * @return the amount of rOUSG that corresponds to `_shares` of OUSG.\n   */\n  function getROUSGByShares(uint256 _shares) public view returns (uint256) {\n    return\n      (_shares * getOUSGPrice()) / (1e18 * OUSG_TO_ROUSG_SHARES_MULTIPLIER);\n  }\n\n  function getOUSGPrice() public view returns (uint256 price) {\n    (price, ) = oracle.getPriceData();\n  }\n\n  /**\n   * @notice Moves `_sharesAmount` token shares from the caller's account to the `_recipient` account.\n   *\n   * @return amount of transferred tokens.\n   * Emits a `TransferShares` event.\n   * Emits a `Transfer` event.\n   *\n   * Requirements:\n   *\n   * - `_recipient` cannot be the zero address.\n   * - the caller must have at least `_sharesAmount` shares.\n   * - the contract must not be paused.\n   *\n   * @dev The `_sharesAmount` argument is the amount of shares, not tokens.\n   */\n  function transferShares(\n    address _recipient,\n    uint256 _sharesAmount\n  ) public returns (uint256) {\n    _transferShares(msg.sender, _recipient, _sharesAmount);\n    emit TransferShares(msg.sender, _recipient, _sharesAmount);\n    uint256 tokensAmount = getROUSGByShares(_sharesAmount);\n    emit Transfer(msg.sender, _recipient, tokensAmount);\n    return tokensAmount;\n  }\n\n  /**\n   * @notice Function called by users to wrap their OUSG tokens\n   *\n   * @param _OUSGAmount The amount of OUSG Tokens to wrap\n   *\n   * @dev KYC checks implicit in OUSG Transfer\n   */\n  function wrap(uint256 _OUSGAmount) external whenNotPaused {\n    require(_OUSGAmount > 0, \"rOUSG: can't wrap zero OUSG tokens\");\n    uint256 ousgSharesAmount = _OUSGAmount * OUSG_TO_ROUSG_SHARES_MULTIPLIER;\n    _mintShares(msg.sender, ousgSharesAmount);\n    ousg.transferFrom(msg.sender, address(this), _OUSGAmount);\n    emit Transfer(address(0), msg.sender, getROUSGByShares(ousgSharesAmount));\n    emit TransferShares(address(0), msg.sender, ousgSharesAmount);\n  }\n\n  /**\n   * @notice Function called by users to unwrap their rOUSG tokens by rOUSG amount\n   *\n   * @param _rOUSGAmount The amount of rOUSG to unwrap\n   *\n   * @dev KYC checks implicit in OUSG Transfer\n   */\n  function unwrap(uint256 _rOUSGAmount) external whenNotPaused {\n    require(_rOUSGAmount > 0, \"rOUSG: can't unwrap zero rOUSG tokens\");\n    uint256 ousgSharesAmount = getSharesByROUSG(_rOUSGAmount);\n    if (ousgSharesAmount < OUSG_TO_ROUSG_SHARES_MULTIPLIER)\n      revert UnwrapTooSmall();\n    _burnShares(msg.sender, ousgSharesAmount);\n    ousg.transfer(\n      msg.sender,\n      ousgSharesAmount / OUSG_TO_ROUSG_SHARES_MULTIPLIER\n    );\n    emit Transfer(msg.sender, address(0), _rOUSGAmount);\n    emit TransferShares(msg.sender, address(0), ousgSharesAmount);\n  }\n\n  /**\n   * @notice Function called by users to unwrap their rOUSG tokens by shares\n   *\n   * @param _sharesAmount The amount of shares to transfer\n   *\n   * @dev KYC checks implicit in OUSG Transfer\n   * @dev This is a more precise unwrap, as it avoids the division by price when converting rOUSG to shares\n   */\n  function unwrapShares(uint256 _sharesAmount) external whenNotPaused {\n    if (_sharesAmount < OUSG_TO_ROUSG_SHARES_MULTIPLIER)\n      revert UnwrapTooSmall();\n\n    uint256 rOUSGAmount = getROUSGByShares(_sharesAmount);\n\n    _burnShares(msg.sender, _sharesAmount);\n    ousg.transfer(msg.sender, _sharesAmount / OUSG_TO_ROUSG_SHARES_MULTIPLIER);\n    emit Transfer(msg.sender, address(0), rOUSGAmount);\n    emit TransferShares(msg.sender, address(0), _sharesAmount);\n  }\n\n  /**\n   * @notice Moves `_amount` tokens from `_sender` to `_recipient`.\n   * Emits a `Transfer` event.\n   * Emits a `TransferShares` event.\n   */\n  function _transfer(\n    address _sender,\n    address _recipient,\n    uint256 _amount\n  ) internal {\n    uint256 _sharesToTransfer = getSharesByROUSG(_amount);\n    _transferShares(_sender, _recipient, _sharesToTransfer);\n    emit Transfer(_sender, _recipient, _amount);\n    emit TransferShares(_sender, _recipient, _sharesToTransfer);\n  }\n\n  /**\n   * @notice Sets `_amount` as the allowance of `_spender` over the `_owner` s tokens.\n   *\n   * Emits an `Approval` event.\n   *\n   * Requirements:\n   *\n   * - `_owner` cannot be the zero address.\n   * - `_spender` cannot be the zero address.\n   * - the contract must not be paused.\n   */\n  function _approve(\n    address _owner,\n    address _spender,\n    uint256 _amount\n  ) internal whenNotPaused {\n    require(_owner != address(0), \"APPROVE_FROM_ZERO_ADDRESS\");\n    require(_spender != address(0), \"APPROVE_TO_ZERO_ADDRESS\");\n\n    allowances[_owner][_spender] = _amount;\n    emit Approval(_owner, _spender, _amount);\n  }\n\n  /**\n   * @return the amount of shares owned by `_account`.\n   */\n  function _sharesOf(address _account) internal view returns (uint256) {\n    return shares[_account];\n  }\n\n  /**\n   * @notice Moves `_sharesAmount` shares from `_sender` to `_recipient`.\n   *\n   * Requirements:\n   *\n   * - `_sender` cannot be the zero address.\n   * - `_recipient` cannot be the zero address.\n   * - `_sender` must hold at least `_sharesAmount` shares.\n   * - the contract must not be paused.\n   */\n  function _transferShares(\n    address _sender,\n    address _recipient,\n    uint256 _sharesAmount\n  ) internal whenNotPaused {\n    require(_sender != address(0), \"TRANSFER_FROM_THE_ZERO_ADDRESS\");\n    require(_recipient != address(0), \"TRANSFER_TO_THE_ZERO_ADDRESS\");\n\n    _beforeTokenTransfer(_sender, _recipient, _sharesAmount);\n\n    uint256 currentSenderShares = shares[_sender];\n    require(\n      _sharesAmount <= currentSenderShares,\n      \"TRANSFER_AMOUNT_EXCEEDS_BALANCE\"\n    );\n\n    shares[_sender] = currentSenderShares - _sharesAmount;\n    shares[_recipient] += _sharesAmount;\n  }\n\n  /**\n   * @notice Creates `_sharesAmount` shares and assigns them to `_recipient`, increasing the total amount of shares.\n   *\n   * Requirements:\n   *\n   * - `_recipient` cannot be the zero address.\n   * - the contract must not be paused.\n   */\n  function _mintShares(address _recipient, uint256 _sharesAmount) internal {\n    require(_recipient != address(0), \"MINT_TO_THE_ZERO_ADDRESS\");\n\n    _beforeTokenTransfer(address(0), _recipient, _sharesAmount);\n\n    totalShares += _sharesAmount;\n\n    shares[_recipient] += _sharesAmount;\n  }\n\n  /**\n   * @notice Destroys `_sharesAmount` shares from `_account`'s holdings, decreasing the total amount of shares.\n   * @dev This doesn't decrease the token total supply.\n   *\n   * Requirements:\n   *\n   * - `_account` cannot be the zero address.\n   * - `_account` must hold at least `_sharesAmount` shares.\n   * - the contract must not be paused.\n   */\n  function _burnShares(address _account, uint256 _sharesAmount) internal {\n    require(_account != address(0), \"BURN_FROM_THE_ZERO_ADDRESS\");\n\n    _beforeTokenTransfer(_account, address(0), _sharesAmount);\n\n    uint256 accountShares = shares[_account];\n    require(_sharesAmount <= accountShares, \"BURN_AMOUNT_EXCEEDS_BALANCE\");\n\n    totalShares -= _sharesAmount;\n\n    shares[_account] = accountShares - _sharesAmount;\n  }\n\n  /**\n   * @dev Hook that is called before any transfer of tokens. This includes\n   * minting and burning.\n   *\n   * Calling conditions:\n   *\n   * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n   * will be transferred to `to`.\n   * - when `from` is zero, `amount` tokens will be minted for `to`.\n   * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n   * - `from` and `to` are never both zero.\n   *\n   * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n   */\n  function _beforeTokenTransfer(\n    address from,\n    address to,\n    uint256\n  ) internal view {\n    // Check constraints when `transferFrom` is called to facliitate\n    // a transfer between two parties that are not `from` or `to`.\n    if (from != msg.sender && to != msg.sender) {\n      require(_getKYCStatus(msg.sender), \"rOUSG: 'sender' address not KYC'd\");\n    }\n\n    if (from != address(0)) {\n      // If not minting\n      require(_getKYCStatus(from), \"rOUSG: 'from' address not KYC'd\");\n    }\n\n    if (to != address(0)) {\n      // If not burning\n      require(_getKYCStatus(to), \"rOUSG: 'to' address not KYC'd\");\n    }\n  }\n\n  /**\n   * @notice Sets the Oracle address\n   * @dev The new oracle must comply with the IRWAOracle interface\n   * @param _oracle Address of the new oracle\n   */\n  function setOracle(address _oracle) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    if (_oracle == address(0)) {\n      revert CannotSetToZeroAddress();\n    }\n    emit OracleSet(address(oracle), _oracle);\n    oracle = IRWAOracle(_oracle);\n  }\n\n  /**\n   * @notice Sets the token name\n   * @param newName New name of the token\n   */\n  function setName(\n    string memory newName\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    emit NameSet(_name, newName);\n    _name = newName;\n  }\n\n  /**\n   * @notice Sets the token symbol\n   * @param newSymbol New symbol of the token\n   */\n  function setSymbol(\n    string memory newSymbol\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    emit SymbolSet(_symbol, newSymbol);\n    _symbol = newSymbol;\n  }\n\n  /**\n   * @notice Admin burn function to burn rOUSG tokens from any account\n   * @param _account The account to burn tokens from\n   * @param _sharesAmount  The amount of OUSG shares to burn\n   * @dev Burns shares and transfers OUSG (if any) to `msg.sender`\n   */\n  function burnShares(\n    address _account,\n    uint256 _sharesAmount\n  ) external onlyRole(BURNER_ROLE) {\n    require(_sharesAmount > 0, \"rOUSG: can't burn zero shares\");\n\n    uint256 rOUSGAmount = getROUSGByShares(_sharesAmount);\n\n    _burnShares(_account, _sharesAmount);\n    emit TransferShares(_account, address(0), _sharesAmount);\n\n    if (_sharesAmount >= OUSG_TO_ROUSG_SHARES_MULTIPLIER) {\n      ousg.transfer(\n        msg.sender,\n        _sharesAmount / OUSG_TO_ROUSG_SHARES_MULTIPLIER\n      );\n      emit Transfer(_account, address(0), rOUSGAmount);\n    }\n  }\n\n  function pause() external onlyRole(PAUSER_ROLE) {\n    _pause();\n  }\n\n  function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _unpause();\n  }\n\n  function setKYCRegistry(\n    address registry\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    _setKYCRegistry(registry);\n  }\n\n  function setKYCRequirementGroup(\n    uint256 group\n  ) external override onlyRole(CONFIGURER_ROLE) {\n    _setKYCRequirementGroup(group);\n  }\n}\n"
      },
      "contracts/interfaces/IOUSGInstantManager.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\n/**\n * @title IOUSGInstantManager\n * @author Ondo Finance\n * @notice The interface for Ondo's conversion modules for between OUSG and USDC\n */\ninterface IOUSGInstantManager {\n  struct RateLimiterConfig {\n    uint256 mintLimitDuration;\n    uint256 redeemLimitDuration;\n    uint256 mintLimit;\n    uint256 redeemLimit;\n  }\n\n  /**\n   * @notice Exchange USDC for OUSG token\n   *\n   * @param usdcAmountIn Amount of USDC to be exchanged for OUSG\n   *\n   * @return ousgAmountOut Amount of OUSG minted for the user\n   */\n  function mint(uint256 usdcAmountIn) external returns (uint256 ousgAmountOut);\n\n  /**\n   * @notice Exchange USDC for rOUSG token\n   *\n   * @param usdcAmountIn Amount of USDC to be exchanged for rOUSG\n   *\n   * @return rousgAmountOut Amount of rOUSG minted for the user\n   */\n\n  function mintRebasingOUSG(\n    uint256 usdcAmountIn\n  ) external returns (uint256 rousgAmountOut);\n\n  /**\n   * @notice Exchange OUSG for USDC\n   *\n   * @param ousgAmountIn Amount of OUSG to redeem for USDC\n   *\n   * @return usdcAmountOut Amount of USDC returned to the user\n   */\n  function redeem(\n    uint256 ousgAmountIn\n  ) external returns (uint256 usdcAmountOut);\n\n  /**\n   * @notice Exchange rOUSG for USDC\n   *\n   * @param rousgAmountIn Amount of rOUSG to redeem for USDC\n   *\n   * @return usdcAmountOut Amount of USDC returned to the user\n   */\n  function redeemRebasingOUSG(\n    uint256 rousgAmountIn\n  ) external returns (uint256 usdcAmountOut);\n\n  /*//////////////////////////////////////////////////////////////\n                    Configuration Setters\n  //////////////////////////////////////////////////////////////*/\n  function setInstantMintLimit(uint256 _instantMintLimit) external;\n\n  function setInstantRedemptionLimit(uint256 _instantRedemptionLimit) external;\n\n  function setInstantMintLimitDuration(\n    uint256 _instantMintLimitDuration\n  ) external;\n\n  function setInstantRedemptionLimitDuration(\n    uint256 _instantRedemptionLimitDuration\n  ) external;\n\n  function setMintFee(uint256 _mintFee) external;\n\n  function setRedeemFee(uint256 _redeemFee) external;\n\n  function setMinimumDepositAmount(uint256 _minimumDepositAmount) external;\n\n  function setMinimumRedemptionAmount(\n    uint256 _minimumRedemptionAmount\n  ) external;\n\n  function setMinimumBUIDLRedemptionAmount(\n    uint256 _minimumBUIDLRedemptionAmount\n  ) external;\n\n  function setUsdcReceiver(address _usdcReceiver) external;\n\n  function setOracle(address _oracle) external;\n\n  function setUSDCOracle(address _oracle) external;\n\n  function setFeeReceiver(address _feeReceiver) external;\n\n  function setInvestorBasedRateLimiter(\n    address _investorBasedRateLimiter\n  ) external;\n\n  /**\n   * @notice Event emitted when a user exchanges USDC for OUSG\n   *\n   * @param sender        Address of the transaction's message sender\n   * @param usdcAmountIn  Amount of the USDC sent from the user\n   * @param ousgAmountOut Amount of OUSG sent to user\n   */\n  event InstantMintOUSG(\n    address indexed sender,\n    uint256 usdcAmountIn,\n    uint256 ousgAmountOut\n  );\n\n  /**\n   * @notice Event emitted when a user exchanges USDC for rOUSG\n   *\n   * @param sender         Address of the transaction's message sender\n   * @param usdcAmountIn   Amount of the USDC sent from the user\n   * @param ousgAmountOut  Amount of OUSG wrapped for the user\n   * @param rousgAmountOut Amount of rOUSG sent to user\n   */\n  event InstantMintRebasingOUSG(\n    address indexed sender,\n    uint256 usdcAmountIn,\n    uint256 ousgAmountOut,\n    uint256 rousgAmountOut\n  );\n\n  /**\n   * @notice Event emitted when a user incurs mint Fees\n   *\n   * @param sender       Address of the transaction's message sender\n   * @param feeReceiver  Address of the USDC fee receiver\n   * @param usdcFees     Amount of USDC deducted as fees\n   * @param usdcAmountIn Amount of USDC sent from the user\n   */\n  event MintFeesDeducted(\n    address indexed sender,\n    address indexed feeReceiver,\n    uint256 usdcFees,\n    uint256 usdcAmountIn\n  );\n\n  /**\n   * @notice Event emitted when a user incurs redemption Fees\n   *\n   * @param sender        Address of the transaction's message sender\n   * @param feeReceiver   Address of the USDC fee receiver\n   * @param usdcFees      Amount of USDC deducted as fees\n   * @param usdcAmountOut Amount of USDC sent to the user\n   */\n  event RedeemFeesDeducted(\n    address indexed sender,\n    address indexed feeReceiver,\n    uint256 usdcFees,\n    uint256 usdcAmountOut\n  );\n\n  /**\n   * @notice Event emitted when a user exchanges OUSG for USDC\n   *\n   * @param sender        Address of the transaction's message sender\n   * @param ousgAmountIn  Amount of the OUSG burned for the redemption\n   * @param usdcAmountOut Amount of usdc sent to the user\n   */\n  event InstantRedemptionOUSG(\n    address indexed sender,\n    uint256 ousgAmountIn,\n    uint256 usdcAmountOut\n  );\n\n  /**\n   * @notice Event emitted when a user exchanges rOUSG for USDC\n   *\n   * @param sender        Address of the transaction's message sender\n   * @param rousgAmountIn Amount of the rOUSG burned for the redemption\n   * @param ousgAmountIn  Amount of OUSG unwrapped for the user\n   * @param usdcAmountOut Amount of USDC sent to the user\n   */\n  event InstantRedemptionRebasingOUSG(\n    address indexed sender,\n    uint256 rousgAmountIn,\n    uint256 ousgAmountIn,\n    uint256 usdcAmountOut\n  );\n\n  /**\n   * @notice Event emitted for when a user performs a redemption of less than\n   *         the minimum BUIDL redemption amount as required by BUIDL and MORE\n   *         than the existing amount of USDC in the contract\n   *\n   * @param sender              Address of the transaction's message sender\n   * @param buidlAmountRedeemed Amount of BUIDL that was redeemed\n   * @param usdcAmountKept      Portion of USDC that was kept in the contract and\n   *                            not sent back to the user\n   */\n  event MinimumBUIDLRedemption(\n    address indexed sender,\n    uint256 buidlAmountRedeemed,\n    uint256 usdcAmountKept\n  );\n\n  /**\n   * @notice Event emitted for when a user performs a redemption of less than\n   *         the minimum BUIDL redemption amount as required by BUIDL and LESS\n   *         than the existing amount of USDC in the contract\n   *\n   * @param sender              Address of the transaction's message sender\n   * @param usdcAmountRedeemed  Amount of USDC sent back to the user\n   * @param usdcAmountRemaining Amount of USDC remaining in the contract\n   */\n  event BUIDLRedemptionSkipped(\n    address indexed sender,\n    uint256 usdcAmountRedeemed,\n    uint256 usdcAmountRemaining\n  );\n\n  /**\n   * @notice Event emitted when mint functionality is paused\n   */\n  event MintPaused();\n\n  /**\n   * @notice Event emitted when mint functionality is unpaused\n   */\n  event MintUnpaused();\n\n  /**\n   * @notice Event emitted when redeem functionality is paused\n   */\n  event RedeemPaused();\n\n  /**\n   * @notice Event emitted when redeem functionality is unpaused\n   */\n  event RedeemUnpaused();\n\n  /**\n   * @notice Event emitted when mint fee is set\n   *\n   * @param oldMintFee Old fee collected for minting OUSG\n   * @param newMintFee New fee collected for minting OUSG\n   *\n   * @dev See inheriting contract for representation\n   */\n  event MintFeeSet(uint256 oldMintFee, uint256 newMintFee);\n\n  /**\n   * @notice Event emitted when redeem fee is set\n   *\n   * @param oldRedeemFee Old fee collected for redeeming OUSG\n   * @param newRedeemFee New fee collected for redeeming OUSG\n   *\n   * @dev See inheriting contract for representation\n   */\n  event RedeemFeeSet(uint256 oldRedeemFee, uint256 newRedeemFee);\n\n  /**\n   * @notice Event emitted when mint limit is set\n   *\n   * @param oldMinDepositAmount Old mint minimum\n   * @param newMinDepositAmount New mint minimum\n   */\n  event MinimumDepositAmountSet(\n    uint256 oldMinDepositAmount,\n    uint256 newMinDepositAmount\n  );\n\n  /**\n   * @notice Event emitted when redeem limit is set\n   *\n   * @param oldMinRedemptionAmount Old redeem minimum\n   * @param newMinRedemptionAmount New redeem minimum\n   */\n  event MinimumRedemptionAmountSet(\n    uint256 oldMinRedemptionAmount,\n    uint256 newMinRedemptionAmount\n  );\n\n  /**\n   * @notice Event emitted when minimum BUIDL redemption amount is set\n   *\n   * @param oldMinBUIDLRedemptionAmount Old minimum BUIDL minimum redemption amount\n   * @param newMinBUIDLRedemptionAmount New minimum BUIDL minimum redemption amount\n   */\n  event MinimumBUIDLRedemptionAmountSet(\n    uint256 oldMinBUIDLRedemptionAmount,\n    uint256 newMinBUIDLRedemptionAmount\n  );\n\n  /**\n   * @notice Event emitted when USDC receiver is set\n   *\n   * @param oldUsdcReceiver Old USDC receiver\n   * @param newUsdcReceiver New USDC receiver\n   */\n  event UsdcReceiverSet(address oldUsdcReceiver, address newUsdcReceiver);\n\n  /**\n   * @notice Event emitted when oracle is set\n   *\n   * @param oldOracle Old oracle address\n   * @param newOracle New oracle address\n   */\n  event OracleSet(address oldOracle, address newOracle);\n\n  /**\n   * @notice Event emitted when USDC oracle is set\n   *\n   * @param oldUSDCOracle Old oracle address\n   * @param newUSDCOracle New oracle address\n   */\n  event USDCOracleSet(address oldUSDCOracle, address newUSDCOracle);\n\n  /**\n   * @notice Event emitted when fee receiver is set\n   *\n   * @param oldFeeReceiver Old fee receiver address\n   * @param newFeeReceiver New fee receiver address\n   */\n  event FeeReceiverSet(address oldFeeReceiver, address newFeeReceiver);\n\n  /**\n   * @notice Event emitted when investor-based rate limiter is set\n   *\n   * @param oldInvestorBasedRateLimiter Old rate limiter address\n   * @param newInvestorBasedRateLimiter New rate limiter address\n   */\n  event InvestorBasedRateLimiterSet(\n    address oldInvestorBasedRateLimiter,\n    address newInvestorBasedRateLimiter\n  );\n}\n"
      },
      "contracts/external/chainlink/AggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.16;\n\ninterface AggregatorV3Interface {\n  function decimals() external view returns (uint8);\n\n  function description() external view returns (string memory);\n\n  function version() external view returns (uint256);\n\n  function getRoundData(\n    uint80 _roundId\n  )\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n\n  function latestRoundData()\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n}\n"
      },
      "contracts/interfaces/IInvestorBasedRateLimiter.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\ninterface IInvestorBasedRateLimiter {\n  /**\n   * @notice Rate limits mints for the provided investor\n   *\n   * @param investorAddress Address of the investor\n   * @param mintAmount Amount of token to be minted\n   *\n   */\n  function checkAndUpdateMintLimit(\n    address investorAddress,\n    uint256 mintAmount\n  ) external;\n\n  /**\n   * @notice Rate limits redemptions for the provided investor\n   *\n   * @param investorAddress Address of the investor\n   * @param redemptionAmount Amount of token to be redeemed\n   *\n   */\n  function checkAndUpdateRedemptionLimit(\n    address investorAddress,\n    uint256 redemptionAmount\n  ) external;\n}\n"
      },
      "contracts/interfaces/IMulticall.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\n/**\n * @title IMulticall\n * @author Ondo Finance\n * @notice This interface dictates the required external functions for Ondo's\n *         multicall contract.\n */\ninterface IMulticall {\n  /// @dev External call data structure\n  struct ExCallData {\n    // The contract we intend to call\n    address target;\n    // The encoded function data for the call\n    bytes data;\n    // The ether value to be sent in the call\n    uint256 value;\n  }\n\n  /**\n   * @notice Batches multiple function calls to different target contracts\n   *         and returns the resulting data provided all calls were successful\n   *\n   * @dev The `msg.sender` is always the contract from which this function\n   *      is being called\n   *\n   * @param exdata The ExCallData struct array containing the information\n   *               regarding which contract to call, what data to call with,\n   *               and what ether value to send along with the call\n   *\n   * @return results The resulting data returned from each call made\n   */\n  function multiexcall(\n    ExCallData[] calldata exdata\n  ) external payable returns (bytes[] memory results);\n}\n"
      },
      "contracts/external/circle/IRedemption.sol": {
        "content": "/**\n * Copyright 2024 Circle Internet Financial, LTD. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.16;\n\n/**\n * @title IRedemption\n */\ninterface IRedemption {\n    /**\n     * @notice The asset being redeemed.\n     * @return The address of the asset token.\n     */\n    function asset() external view returns (address);\n\n    /**\n     * @notice The liquidity token that the asset is being redeemed for.\n     * @return The address of the liquidity token.\n     */\n    function liquidity() external view returns (address);\n\n    /**\n     * @notice Redeems an amount of asset for liquidity\n     * @param amount The amount of the asset token to redeem\n     */\n    function redeem(uint256 amount) external;\n}\n"
      },
      "contracts/external/openzeppelin/contracts/access/AccessControlEnumerable.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/security/ReentrancyGuard.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/token/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/token/IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n  /**\n   * @dev Returns the name of the token.\n   */\n  function name() external view returns (string memory);\n\n  /**\n   * @dev Returns the symbol of the token.\n   */\n  function symbol() external view returns (string memory);\n\n  /**\n   * @dev Returns the decimals places of the token.\n   */\n  function decimals() external view returns (uint8);\n}\n"
      },
      "contracts/external/openzeppelin/contracts/token/IERC20.sol": {
        "content": "// 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"
      },
      "contracts/kyc/KYCRegistryClientUpgradeable.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/kyc/IKYCRegistry.sol\";\nimport \"contracts/kyc/IKYCRegistryClient.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @title KYCRegistryClientInitializable\n * @author Ondo Finance\n * @notice This abstract contract manages state required for clients\n *         of the KYC registry.\n */\nabstract contract KYCRegistryClientUpgradeable is\n  Initializable,\n  IKYCRegistryClient\n{\n  // KYC Registry address\n  IKYCRegistry public override kycRegistry;\n  // KYC requirement group\n  uint256 public override kycRequirementGroup;\n\n  /**\n   * @notice Initialize the contract by setting registry variable\n   *\n   * @param _kycRegistry         Address of the registry contract\n   * @param _kycRequirementGroup KYC requirement group associated with this\n   *                             client\n   *\n   * @dev Function should be called by the inheriting contract on\n   *      initialization\n   */\n  function __KYCRegistryClientInitializable_init(\n    address _kycRegistry,\n    uint256 _kycRequirementGroup\n  ) internal onlyInitializing {\n    __KYCRegistryClientInitializable_init_unchained(\n      _kycRegistry,\n      _kycRequirementGroup\n    );\n  }\n\n  /**\n   * @dev Internal function to future-proof parent linearization. Matches OZ\n   *      upgradeable suggestions\n   */\n  function __KYCRegistryClientInitializable_init_unchained(\n    address _kycRegistry,\n    uint256 _kycRequirementGroup\n  ) internal onlyInitializing {\n    _setKYCRegistry(_kycRegistry);\n    _setKYCRequirementGroup(_kycRequirementGroup);\n  }\n\n  /**\n   * @notice Sets the KYC registry address for this client\n   *\n   * @param _kycRegistry The new KYC registry address\n   */\n  function _setKYCRegistry(address _kycRegistry) internal {\n    if (_kycRegistry == address(0)) {\n      revert RegistryZeroAddress();\n    }\n    address oldKYCRegistry = address(kycRegistry);\n    kycRegistry = IKYCRegistry(_kycRegistry);\n    emit KYCRegistrySet(oldKYCRegistry, _kycRegistry);\n  }\n\n  /**\n   * @notice Sets the KYC registry requirement group for this\n   *         client to check kyc status for\n   *\n   * @param _kycRequirementGroup The new KYC group\n   */\n  function _setKYCRequirementGroup(uint256 _kycRequirementGroup) internal {\n    uint256 oldKYCLevel = kycRequirementGroup;\n    kycRequirementGroup = _kycRequirementGroup;\n    emit KYCRequirementGroupSet(oldKYCLevel, _kycRequirementGroup);\n  }\n\n  /**\n   * @notice Checks whether an address has been KYC'd\n   *\n   * @param account The address to check\n   */\n  function _getKYCStatus(address account) internal view returns (bool) {\n    return kycRegistry.getKYCStatus(kycRequirementGroup, account);\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/rwaOracles/IRWAOracle.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\ninterface IRWAOracle {\n  /// @notice Retrieve RWA price data\n  function getPriceData()\n    external\n    view\n    returns (uint256 price, uint256 timestamp);\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"contracts/external/openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n  function __Context_init() internal onlyInitializing {}\n\n  function __Context_init_unchained() internal onlyInitializing {}\n\n  function _msgSender() internal view virtual returns (address) {\n    return msg.sender;\n  }\n\n  function _msgData() internal view virtual returns (bytes calldata) {\n    return msg.data;\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/proxy/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"contracts/external/openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n  /**\n   * @dev Indicates that the contract has been initialized.\n   * @custom:oz-retyped-from bool\n   */\n  uint8 private _initialized;\n\n  /**\n   * @dev Indicates that the contract is in the process of being initialized.\n   */\n  bool private _initializing;\n\n  /**\n   * @dev Triggered when the contract has been initialized or reinitialized.\n   */\n  event Initialized(uint8 version);\n\n  /**\n   * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n   * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n   */\n  modifier initializer() {\n    bool isTopLevelCall = !_initializing;\n    require(\n      (isTopLevelCall && _initialized < 1) ||\n        (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n      \"Initializable: contract is already initialized\"\n    );\n    _initialized = 1;\n    if (isTopLevelCall) {\n      _initializing = true;\n    }\n    _;\n    if (isTopLevelCall) {\n      _initializing = false;\n      emit Initialized(1);\n    }\n  }\n\n  /**\n   * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n   * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n   * used to initialize parent contracts.\n   *\n   * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n   * initialization step. This is essential to configure modules that are added through upgrades and that require\n   * initialization.\n   *\n   * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n   * a contract, executing them in the right order is up to the developer or operator.\n   */\n  modifier reinitializer(uint8 version) {\n    require(\n      !_initializing && _initialized < version,\n      \"Initializable: contract is already initialized\"\n    );\n    _initialized = version;\n    _initializing = true;\n    _;\n    _initializing = false;\n    emit Initialized(version);\n  }\n\n  /**\n   * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n   * {initializer} and {reinitializer} modifiers, directly or indirectly.\n   */\n  modifier onlyInitializing() {\n    require(_initializing, \"Initializable: contract is not initializing\");\n    _;\n  }\n\n  /**\n   * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n   * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n   * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n   * through proxies.\n   */\n  function _disableInitializers() internal virtual {\n    require(!_initializing, \"Initializable: contract is initializing\");\n    if (_initialized < type(uint8).max) {\n      _initialized = type(uint8).max;\n      emit Initialized(type(uint8).max);\n    }\n  }\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol": {
        "content": "// 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-upgradeable/access/IAccessControlEnumerableUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerableUpgradeable is\n  Initializable,\n  IAccessControlEnumerableUpgradeable,\n  AccessControlUpgradeable\n{\n  function __AccessControlEnumerable_init() internal onlyInitializing {}\n\n  function __AccessControlEnumerable_init_unchained()\n    internal\n    onlyInitializing\n  {}\n\n  using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n  mapping(bytes32 => EnumerableSetUpgradeable.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(IAccessControlEnumerableUpgradeable).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  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[49] private __gap;\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n  /**\n   * @dev Emitted when the pause is triggered by `account`.\n   */\n  event Paused(address account);\n\n  /**\n   * @dev Emitted when the pause is lifted by `account`.\n   */\n  event Unpaused(address account);\n\n  bool private _paused;\n\n  /**\n   * @dev Initializes the contract in unpaused state.\n   */\n  function __Pausable_init() internal onlyInitializing {\n    __Pausable_init_unchained();\n  }\n\n  function __Pausable_init_unchained() internal onlyInitializing {\n    _paused = false;\n  }\n\n  /**\n   * @dev Modifier to make a function callable only when the contract is not paused.\n   *\n   * Requirements:\n   *\n   * - The contract must not be paused.\n   */\n  modifier whenNotPaused() {\n    _requireNotPaused();\n    _;\n  }\n\n  /**\n   * @dev Modifier to make a function callable only when the contract is paused.\n   *\n   * Requirements:\n   *\n   * - The contract must be paused.\n   */\n  modifier whenPaused() {\n    _requirePaused();\n    _;\n  }\n\n  /**\n   * @dev Returns true if the contract is paused, and false otherwise.\n   */\n  function paused() public view virtual returns (bool) {\n    return _paused;\n  }\n\n  /**\n   * @dev Throws if the contract is paused.\n   */\n  function _requireNotPaused() internal view virtual {\n    require(!paused(), \"Pausable: paused\");\n  }\n\n  /**\n   * @dev Throws if the contract is not paused.\n   */\n  function _requirePaused() internal view virtual {\n    require(paused(), \"Pausable: not paused\");\n  }\n\n  /**\n   * @dev Triggers stopped state.\n   *\n   * Requirements:\n   *\n   * - The contract must not be paused.\n   */\n  function _pause() internal virtual whenNotPaused {\n    _paused = true;\n    emit Paused(_msgSender());\n  }\n\n  /**\n   * @dev Returns to normal state.\n   *\n   * Requirements:\n   *\n   * - The contract must be paused.\n   */\n  function _unpause() internal virtual whenPaused {\n    _paused = false;\n    emit Unpaused(_msgSender());\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[49] private __gap;\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 IERC20Upgradeable {\n  /**\n   * @dev Emitted when `value` tokens are moved from one account (`from`) to\n   * another (`to`).\n   *\n   * Note that `value` may be zero.\n   */\n  event Transfer(address indexed from, address indexed to, uint256 value);\n\n  /**\n   * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n   * a call to {approve}. `value` is the new allowance.\n   */\n  event Approval(address indexed owner, address indexed spender, uint256 value);\n\n  /**\n   * @dev Returns the 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"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/token/ERC20/IERC20MetadataUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n  /**\n   * @dev Returns the name of the token.\n   */\n  function name() external view returns (string memory);\n\n  /**\n   * @dev Returns the symbol of the token.\n   */\n  function symbol() external view returns (string memory);\n\n  /**\n   * @dev Returns the decimals places of the token.\n   */\n  function decimals() external view returns (uint8);\n}\n"
      },
      "contracts/kyc/IKYCRegistry.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\n/**\n * @title IKYCRegistry\n * @author Ondo Finance\n * @notice The interface for Ondo's KYC Registry contract\n */\ninterface IKYCRegistry {\n  /**\n   * @notice Retrieves KYC status of an account\n   *\n   * @param kycRequirementGroup The KYC group for which we wish to check\n   * @param account             The account we wish to retrieve KYC status for\n   *\n   * @return bool Whether the `account` is KYC'd\n   */\n  function getKYCStatus(\n    uint256 kycRequirementGroup,\n    address account\n  ) external view returns (bool);\n\n  /**\n   * @notice View function for the public nested mapping of kycState\n   *\n   * @param kycRequirementGroup The KYC group to view\n   * @param account             The account to check if KYC'd\n   */\n  function kycState(\n    uint256 kycRequirementGroup,\n    address account\n  ) external view returns (bool);\n}\n"
      },
      "contracts/kyc/IKYCRegistryClient.sol": {
        "content": "/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/kyc/IKYCRegistry.sol\";\n\n/**\n * @title IKYCRegistryClient\n * @author Ondo Finance\n * @notice The client interface Ondo's KYC Registry contract.\n */\ninterface IKYCRegistryClient {\n  /// @notice Returns what KYC group this client checks accounts for\n  function kycRequirementGroup() external view returns (uint256);\n\n  /// @notice Returns reference to the KYC registry that this client queries\n  function kycRegistry() external view returns (IKYCRegistry);\n\n  /// @notice Sets the KYC group\n  function setKYCRequirementGroup(uint256 group) external;\n\n  /// @notice Sets the KYC registry reference\n  function setKYCRegistry(address registry) external;\n\n  /// @notice Error for when caller attempts to set the KYC registry refernce\n  ///         to the zero address.\n  error RegistryZeroAddress();\n\n  /**\n   * @dev Event for when the KYC registry reference is set\n   *\n   * @param oldRegistry The old registry\n   * @param newRegistry The new registry\n   */\n  event KYCRegistrySet(address oldRegistry, address newRegistry);\n\n  /**\n   * @dev Event for when the KYC group for this client is set\n   *\n   * @param oldRequirementGroup The old KYC group\n   * @param newRequirementGroup The new KYC group\n   */\n  event KYCRequirementGroupSet(\n    uint256 oldRequirementGroup,\n    uint256 newRequirementGroup\n  );\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n  /**\n   * @dev Returns true if `account` is a contract.\n   *\n   * [IMPORTANT]\n   * ====\n   * It is unsafe to assume that an address for which this function returns\n   * false is an externally-owned account (EOA) and not a contract.\n   *\n   * Among others, `isContract` will return false for the following\n   * types of addresses:\n   *\n   *  - an externally-owned account\n   *  - a contract in construction\n   *  - an address where a contract will be created\n   *  - an address where a contract lived, but was destroyed\n   * ====\n   *\n   * [IMPORTANT]\n   * ====\n   * You shouldn't rely on `isContract` to protect against flash loan attacks!\n   *\n   * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n   * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n   * constructor.\n   * ====\n   */\n  function isContract(address account) internal view returns (bool) {\n    // This method relies on extcodesize/address.code.length, which returns 0\n    // for contracts in construction, since the code is only stored at the end\n    // of the constructor execution.\n\n    return account.code.length > 0;\n  }\n\n  /**\n   * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n   * `recipient`, forwarding all available gas and reverting on errors.\n   *\n   * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n   * of certain opcodes, possibly making contracts go over the 2300 gas limit\n   * imposed by `transfer`, making them unable to receive funds via\n   * `transfer`. {sendValue} removes this limitation.\n   *\n   * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n   *\n   * IMPORTANT: because control is transferred to `recipient`, care must be\n   * taken to not create reentrancy vulnerabilities. Consider using\n   * {ReentrancyGuard} or the\n   * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n   */\n  function sendValue(address payable recipient, uint256 amount) internal {\n    require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n    (bool success, ) = recipient.call{value: amount}(\"\");\n    require(\n      success,\n      \"Address: unable to send value, recipient may have reverted\"\n    );\n  }\n\n  /**\n   * @dev Performs a Solidity function call using a low level `call`. A\n   * plain `call` is an unsafe replacement for a function call: use this\n   * function instead.\n   *\n   * If `target` reverts with a revert reason, it is bubbled up by this\n   * function (like regular Solidity function calls).\n   *\n   * Returns the raw returned data. To convert to the expected return value,\n   * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n   *\n   * Requirements:\n   *\n   * - `target` must be a contract.\n   * - calling `target` with `data` must not revert.\n   *\n   * _Available since v3.1._\n   */\n  function functionCall(address target, bytes memory data)\n    internal\n    returns (bytes memory)\n  {\n    return functionCall(target, data, \"Address: low-level call failed\");\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n   * `errorMessage` as a fallback revert reason when `target` reverts.\n   *\n   * _Available since v3.1._\n   */\n  function functionCall(\n    address target,\n    bytes memory data,\n    string memory errorMessage\n  ) internal returns (bytes memory) {\n    return functionCallWithValue(target, data, 0, errorMessage);\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n   * but also transferring `value` wei to `target`.\n   *\n   * Requirements:\n   *\n   * - the calling contract must have an ETH balance of at least `value`.\n   * - the called Solidity function must be `payable`.\n   *\n   * _Available since v3.1._\n   */\n  function functionCallWithValue(\n    address target,\n    bytes memory data,\n    uint256 value\n  ) internal returns (bytes memory) {\n    return\n      functionCallWithValue(\n        target,\n        data,\n        value,\n        \"Address: low-level call with value failed\"\n      );\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n   * with `errorMessage` as a fallback revert reason when `target` reverts.\n   *\n   * _Available since v3.1._\n   */\n  function functionCallWithValue(\n    address target,\n    bytes memory data,\n    uint256 value,\n    string memory errorMessage\n  ) internal returns (bytes memory) {\n    require(\n      address(this).balance >= value,\n      \"Address: insufficient balance for call\"\n    );\n    require(isContract(target), \"Address: call to non-contract\");\n\n    (bool success, bytes memory returndata) = target.call{value: value}(data);\n    return verifyCallResult(success, returndata, errorMessage);\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n   * but performing a static call.\n   *\n   * _Available since v3.3._\n   */\n  function functionStaticCall(address target, bytes memory data)\n    internal\n    view\n    returns (bytes memory)\n  {\n    return\n      functionStaticCall(target, data, \"Address: low-level static call failed\");\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n   * but performing a static call.\n   *\n   * _Available since v3.3._\n   */\n  function functionStaticCall(\n    address target,\n    bytes memory data,\n    string memory errorMessage\n  ) internal view returns (bytes memory) {\n    require(isContract(target), \"Address: static call to non-contract\");\n\n    (bool success, bytes memory returndata) = target.staticcall(data);\n    return verifyCallResult(success, returndata, errorMessage);\n  }\n\n  /**\n   * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n   * revert reason using the provided one.\n   *\n   * _Available since v4.3._\n   */\n  function verifyCallResult(\n    bool success,\n    bytes memory returndata,\n    string memory errorMessage\n  ) internal pure returns (bytes memory) {\n    if (success) {\n      return returndata;\n    } else {\n      // Look for revert reason and bubble it up if present\n      if (returndata.length > 0) {\n        // The easiest way to bubble the revert reason is using memory via assembly\n        /// @solidity memory-safe-assembly\n        assembly {\n          let returndata_size := mload(returndata)\n          revert(add(32, returndata), returndata_size)\n        }\n      } else {\n        revert(errorMessage);\n      }\n    }\n  }\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/access/IAccessControlEnumerableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlUpgradeable.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerableUpgradeable is IAccessControlUpgradeable {\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"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/utils/ERC165Upgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\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 AccessControlUpgradeable is\n  Initializable,\n  ContextUpgradeable,\n  IAccessControlUpgradeable,\n  ERC165Upgradeable\n{\n  function __AccessControl_init() internal onlyInitializing {}\n\n  function __AccessControl_init_unchained() internal onlyInitializing {}\n\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);\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(IAccessControlUpgradeable).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 `_msgSender()` is missing `role`.\n   * Overriding this function changes the behavior of the {onlyRole} modifier.\n   *\n   * Format of the revert message is described in {_checkRole}.\n   *\n   * _Available since v4.6._\n   */\n  function _checkRole(bytes32 role) internal view virtual {\n    _checkRole(role, _msgSender());\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            StringsUpgradeable.toHexString(uint160(account), 20),\n            \" is missing role \",\n            StringsUpgradeable.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   * May emit a {RoleGranted} event.\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   * May emit a {RoleRevoked} event.\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   * May emit a {RoleRevoked} event.\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   * May emit a {RoleGranted} event.\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   * May emit a {RoleGranted} event.\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   * May emit a {RoleRevoked} event.\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  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[49] private __gap;\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 *\n * [WARNING]\n * ====\n *  Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.\n *  See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n *  In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSetUpgradeable {\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    /// @solidity memory-safe-assembly\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    /// @solidity memory-safe-assembly\n    assembly {\n      result := store\n    }\n\n    return result;\n  }\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControlUpgradeable {\n  /**\n   * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n   *\n   * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n   * {RoleAdminChanged} not being emitted signaling this.\n   *\n   * _Available since v3.1._\n   */\n  event RoleAdminChanged(\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"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n  bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n  uint8 private constant _ADDRESS_LENGTH = 20;\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  /**\n   * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n   */\n  function toHexString(address addr) internal pure returns (string memory) {\n    return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n  }\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/utils/ERC165Upgradeable.sol": {
        "content": "// 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-upgradeable/utils/IERC165Upgradeable.sol\";\nimport \"contracts/external/openzeppelin/contracts-upgradeable/proxy/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable {\n  function __ERC165_init() internal onlyInitializing {}\n\n  function __ERC165_init_unchained() internal onlyInitializing {}\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 interfaceId == type(IERC165Upgradeable).interfaceId;\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"
      },
      "contracts/external/openzeppelin/contracts-upgradeable/utils/IERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n  /**\n   * @dev Returns true if this contract implements the interface defined by\n   * `interfaceId`. See the corresponding\n   * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n   * to learn more about how these ids are created.\n   *\n   * This function call must use less than 30 000 gas.\n   */\n  function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "contracts/external/openzeppelin/contracts/access/IAccessControlEnumerable.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/utils/EnumerableSet.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/access/AccessControl.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/access/IAccessControl.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/utils/Context.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/utils/Strings.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/utils/ERC165.sol": {
        "content": "// 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"
      },
      "contracts/external/openzeppelin/contracts/utils/IERC165.sol": {
        "content": "// 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"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 100
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}