{
  "address": "0x78a486306D15E7111cca541F2f1307a1cFCaF5C4",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_usdcAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_maiAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_lpAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_qiAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_quickSwapRouterAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_qiDaoFarmAddress",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_qiDaoPoolId",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "Approval",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "QiQuantity",
          "name": "qi",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "UsdcQuantity",
          "name": "usdc",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "LpQuantity",
          "name": "lp",
          "type": "uint256"
        }
      ],
      "name": "CompoundRewards",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "UsdcQuantity",
          "name": "collateral",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "PePerUsdcQuantity",
          "name": "startingRatio",
          "type": "uint256"
        }
      ],
      "name": "Initialized",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "LpQuantity",
          "name": "lpAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "PeQuantity",
          "name": "tokenAmount",
          "type": "uint256"
        }
      ],
      "name": "LiquidityWithdrawal",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "RatioWith6Decimals",
          "name": "markupFee",
          "type": "uint256"
        }
      ],
      "name": "MarkupFeeUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "UsdcQuantity",
          "name": "collateralAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "PeQuantity",
          "name": "tokenAmount",
          "type": "uint256"
        }
      ],
      "name": "Minted",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "previousAdminRole",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "newAdminRole",
          "type": "bytes32"
        }
      ],
      "name": "RoleAdminChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "sender",
          "type": "address"
        }
      ],
      "name": "RoleGranted",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "sender",
          "type": "address"
        }
      ],
      "name": "RoleRevoked",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "Transfer",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "UsdcQuantity",
          "name": "collateralAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "PeQuantity",
          "name": "tokenAmount",
          "type": "uint256"
        }
      ],
      "name": "Withdrawal",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "DEFAULT_ADMIN_ROLE",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "DOMAIN_SEPARATOR",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "MARKUP_ROLE",
      "outputs": [
        {
          "internalType": "RoleId",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "MIGRATOR_ROLE",
      "outputs": [
        {
          "internalType": "RoleId",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "REWARDS_ROLE",
      "outputs": [
        {
          "internalType": "RoleId",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        }
      ],
      "name": "allowance",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "approve",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "balanceOf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "burn",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "burnFrom",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "buyingPrice",
      "outputs": [
        {
          "internalType": "UsdcPerPeQuantity",
          "name": "price",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "collateralRatio",
      "outputs": [
        {
          "internalType": "UsdcPerPeQuantity",
          "name": "ratio",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "compoundRewards",
      "outputs": [
        {
          "internalType": "UsdcQuantity",
          "name": "usdcAmount",
          "type": "uint256"
        },
        {
          "internalType": "LpQuantity",
          "name": "lpAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "decimals",
      "outputs": [
        {
          "internalType": "uint8",
          "name": "decimals_",
          "type": "uint8"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "subtractedValue",
          "type": "uint256"
        }
      ],
      "name": "decreaseAllowance",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getLpReserves",
      "outputs": [
        {
          "internalType": "UsdcQuantity",
          "name": "usdcReserves",
          "type": "uint256"
        },
        {
          "internalType": "MaiQuantity",
          "name": "maiReserves",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getPendingRewardsAmount",
      "outputs": [
        {
          "internalType": "QiQuantity",
          "name": "qiAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        }
      ],
      "name": "getRoleAdmin",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "grantRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "hasRole",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "addedValue",
          "type": "uint256"
        }
      ],
      "name": "increaseAllowance",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "UsdcQuantity",
          "name": "usdcAmount",
          "type": "uint256"
        },
        {
          "internalType": "PePerUsdcQuantity",
          "name": "startingRatio",
          "type": "uint256"
        }
      ],
      "name": "initialize",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "initialized",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "lpAddress",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "maiAddress",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "markupFee",
      "outputs": [
        {
          "internalType": "RatioWith6Decimals",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "UsdcQuantity",
          "name": "usdcAmount",
          "type": "uint256"
        },
        {
          "internalType": "PeQuantity",
          "name": "minReceive",
          "type": "uint256"
        }
      ],
      "name": "mint",
      "outputs": [
        {
          "internalType": "PeQuantity",
          "name": "peAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "UsdcQuantity",
          "name": "usdcAmount",
          "type": "uint256"
        },
        {
          "internalType": "PeQuantity",
          "name": "minReceive",
          "type": "uint256"
        }
      ],
      "name": "mintForMigration",
      "outputs": [
        {
          "internalType": "PeQuantity",
          "name": "peAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "name",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        }
      ],
      "name": "nonces",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "deadline",
          "type": "uint256"
        },
        {
          "internalType": "uint8",
          "name": "v",
          "type": "uint8"
        },
        {
          "internalType": "bytes32",
          "name": "r",
          "type": "bytes32"
        },
        {
          "internalType": "bytes32",
          "name": "s",
          "type": "bytes32"
        }
      ],
      "name": "permit",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "qiAddress",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "qiDaoFarmAddress",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "qiDaoPoolId",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "quickSwapRouterAddress",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "UsdcQuantity",
          "name": "usdc",
          "type": "uint256"
        }
      ],
      "name": "quoteIn",
      "outputs": [
        {
          "internalType": "PeQuantity",
          "name": "pe",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "PeQuantity",
          "name": "pe",
          "type": "uint256"
        }
      ],
      "name": "quoteOut",
      "outputs": [
        {
          "internalType": "UsdcQuantity",
          "name": "usdc",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "renounceRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "revokeRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "RatioWith6Decimals",
          "name": "newMarkupFee",
          "type": "uint256"
        }
      ],
      "name": "setMarkupFee",
      "outputs": [
        {
          "internalType": "RatioWith6Decimals",
          "name": "prevMarkupFee",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "stakedBalance",
      "outputs": [
        {
          "internalType": "LpQuantity",
          "name": "lpAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "stakedTokens",
      "outputs": [
        {
          "internalType": "UsdcQuantity",
          "name": "usdcAmount",
          "type": "uint256"
        },
        {
          "internalType": "MaiQuantity",
          "name": "maiAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "stakedValue",
      "outputs": [
        {
          "internalType": "UsdcQuantity",
          "name": "usdcAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes4",
          "name": "interfaceId",
          "type": "bytes4"
        }
      ],
      "name": "supportsInterface",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "swapFee",
      "outputs": [
        {
          "internalType": "RatioWith6Decimals",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "symbol",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "totalSupply",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "transfer",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "transferFrom",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "usdcAddress",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "usdcPrice",
      "outputs": [
        {
          "internalType": "PePerUsdcQuantity",
          "name": "price",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "PeQuantity",
          "name": "peAmount",
          "type": "uint256"
        }
      ],
      "name": "withdraw",
      "outputs": [
        {
          "internalType": "UsdcQuantity",
          "name": "usdcTotal",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "PeQuantity",
          "name": "peAmount",
          "type": "uint256"
        }
      ],
      "name": "withdrawLiquidity",
      "outputs": [
        {
          "internalType": "LpQuantity",
          "name": "lpAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0x9087755d8f46c562250d49ac56cf4f591ecf174865b453aef1027c695fa7bbdb",
  "receipt": {
    "to": null,
    "from": "0x4BADCf0DCeaAD060f86D9b34c9E118c8319945AE",
    "contractAddress": "0x78a486306D15E7111cca541F2f1307a1cFCaF5C4",
    "transactionIndex": 49,
    "gasUsed": "4122267",
    "logsBloom": "0x00000014000000000000000000000000a00000000000000000000000000000400000000000008000000080000000000000008000000000000000000000000000000080000000000000000000000000800000000000000000000100000000000000400000020000000000000000400800000000000000000080000000000000000000000000000000000400000000000000000000002000000000800000080000200000000000000000000000000000000000000000000000001000000000004000000000800000000001000000004000000000000000000100100001000020000000000000000000000000002000000000002000000000000000000000100000",
    "blockHash": "0x0a90cab69c1dac00d01e012c0163b66b5a323f6fff1526ec251e5d3214be60c3",
    "transactionHash": "0x9087755d8f46c562250d49ac56cf4f591ecf174865b453aef1027c695fa7bbdb",
    "logs": [
      {
        "transactionIndex": 49,
        "blockNumber": 33279670,
        "transactionHash": "0x9087755d8f46c562250d49ac56cf4f591ecf174865b453aef1027c695fa7bbdb",
        "address": "0x78a486306D15E7111cca541F2f1307a1cFCaF5C4",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae"
        ],
        "data": "0x",
        "logIndex": 209,
        "blockHash": "0x0a90cab69c1dac00d01e012c0163b66b5a323f6fff1526ec251e5d3214be60c3"
      },
      {
        "transactionIndex": 49,
        "blockNumber": 33279670,
        "transactionHash": "0x9087755d8f46c562250d49ac56cf4f591ecf174865b453aef1027c695fa7bbdb",
        "address": "0x78a486306D15E7111cca541F2f1307a1cFCaF5C4",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x74a064b2dec4aeb0b53e2d06f8e76ce531a17302a866fe51bc86d9a90b4e85e3",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae"
        ],
        "data": "0x",
        "logIndex": 210,
        "blockHash": "0x0a90cab69c1dac00d01e012c0163b66b5a323f6fff1526ec251e5d3214be60c3"
      },
      {
        "transactionIndex": 49,
        "blockNumber": 33279670,
        "transactionHash": "0x9087755d8f46c562250d49ac56cf4f591ecf174865b453aef1027c695fa7bbdb",
        "address": "0x78a486306D15E7111cca541F2f1307a1cFCaF5C4",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x5407862f04286ebe607684514c14b7fffc750b6bf52ba44ea49569174845a5bd",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae"
        ],
        "data": "0x",
        "logIndex": 211,
        "blockHash": "0x0a90cab69c1dac00d01e012c0163b66b5a323f6fff1526ec251e5d3214be60c3"
      },
      {
        "transactionIndex": 49,
        "blockNumber": 33279670,
        "transactionHash": "0x9087755d8f46c562250d49ac56cf4f591ecf174865b453aef1027c695fa7bbdb",
        "address": "0x78a486306D15E7111cca541F2f1307a1cFCaF5C4",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x600e5f1c60beb469a3fa6dd3814a4ae211cc6259a6d033bae218a742f2af01d3",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae"
        ],
        "data": "0x",
        "logIndex": 212,
        "blockHash": "0x0a90cab69c1dac00d01e012c0163b66b5a323f6fff1526ec251e5d3214be60c3"
      },
      {
        "transactionIndex": 49,
        "blockNumber": 33279670,
        "transactionHash": "0x9087755d8f46c562250d49ac56cf4f591ecf174865b453aef1027c695fa7bbdb",
        "address": "0x0000000000000000000000000000000000001010",
        "topics": [
          "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
          "0x0000000000000000000000000000000000000000000000000000000000001010",
          "0x0000000000000000000000004badcf0dceaad060f86d9b34c9e118c8319945ae",
          "0x000000000000000000000000f0245f6251bef9447a08766b9da2b07b28ad80b0"
        ],
        "data": "0x00000000000000000000000000000000000000000000000001b75b665e600a9b0000000000000000000000000000000000000000000000d349b01a4133b058e80000000000000000000000000000000000000000000002399a33a3b78ee22a480000000000000000000000000000000000000000000000d347f8bedad5504e4d0000000000000000000000000000000000000000000002399beaff1ded4234e3",
        "logIndex": 213,
        "blockHash": "0x0a90cab69c1dac00d01e012c0163b66b5a323f6fff1526ec251e5d3214be60c3"
      }
    ],
    "blockNumber": 33279670,
    "cumulativeGasUsed": "12496790",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
    "0xa3Fa99A148fA48D14Ed51d610c367C61876997F1",
    "0x160532D2536175d65C03B97b0630A9802c274daD",
    "0x580A84C73811E1839F75d86d75d88cCa0c241fF4",
    "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff",
    "0xFFD2AA58Cca3A44120aaA42CEA2852348A9c2eA6",
    "0"
  ],
  "numDeployments": 2,
  "solcInputHash": "c8f91a6888129fb6399da91a46326481",
  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_usdcAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_maiAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_lpAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_qiAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_quickSwapRouterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_qiDaoFarmAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_qiDaoPoolId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"QiQuantity\",\"name\":\"qi\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UsdcQuantity\",\"name\":\"usdc\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"LpQuantity\",\"name\":\"lp\",\"type\":\"uint256\"}],\"name\":\"CompoundRewards\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"UsdcQuantity\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"PePerUsdcQuantity\",\"name\":\"startingRatio\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"LpQuantity\",\"name\":\"lpAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"PeQuantity\",\"name\":\"tokenAmount\",\"type\":\"uint256\"}],\"name\":\"LiquidityWithdrawal\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"RatioWith6Decimals\",\"name\":\"markupFee\",\"type\":\"uint256\"}],\"name\":\"MarkupFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"UsdcQuantity\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"PeQuantity\",\"name\":\"tokenAmount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"UsdcQuantity\",\"name\":\"collateralAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"PeQuantity\",\"name\":\"tokenAmount\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKUP_ROLE\",\"outputs\":[{\"internalType\":\"RoleId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIGRATOR_ROLE\",\"outputs\":[{\"internalType\":\"RoleId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REWARDS_ROLE\",\"outputs\":[{\"internalType\":\"RoleId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"buyingPrice\",\"outputs\":[{\"internalType\":\"UsdcPerPeQuantity\",\"name\":\"price\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"collateralRatio\",\"outputs\":[{\"internalType\":\"UsdcPerPeQuantity\",\"name\":\"ratio\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"compoundRewards\",\"outputs\":[{\"internalType\":\"UsdcQuantity\",\"name\":\"usdcAmount\",\"type\":\"uint256\"},{\"internalType\":\"LpQuantity\",\"name\":\"lpAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLpReserves\",\"outputs\":[{\"internalType\":\"UsdcQuantity\",\"name\":\"usdcReserves\",\"type\":\"uint256\"},{\"internalType\":\"MaiQuantity\",\"name\":\"maiReserves\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPendingRewardsAmount\",\"outputs\":[{\"internalType\":\"QiQuantity\",\"name\":\"qiAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UsdcQuantity\",\"name\":\"usdcAmount\",\"type\":\"uint256\"},{\"internalType\":\"PePerUsdcQuantity\",\"name\":\"startingRatio\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lpAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maiAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"markupFee\",\"outputs\":[{\"internalType\":\"RatioWith6Decimals\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"UsdcQuantity\",\"name\":\"usdcAmount\",\"type\":\"uint256\"},{\"internalType\":\"PeQuantity\",\"name\":\"minReceive\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"PeQuantity\",\"name\":\"peAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"UsdcQuantity\",\"name\":\"usdcAmount\",\"type\":\"uint256\"},{\"internalType\":\"PeQuantity\",\"name\":\"minReceive\",\"type\":\"uint256\"}],\"name\":\"mintForMigration\",\"outputs\":[{\"internalType\":\"PeQuantity\",\"name\":\"peAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"qiAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"qiDaoFarmAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"qiDaoPoolId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quickSwapRouterAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UsdcQuantity\",\"name\":\"usdc\",\"type\":\"uint256\"}],\"name\":\"quoteIn\",\"outputs\":[{\"internalType\":\"PeQuantity\",\"name\":\"pe\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"PeQuantity\",\"name\":\"pe\",\"type\":\"uint256\"}],\"name\":\"quoteOut\",\"outputs\":[{\"internalType\":\"UsdcQuantity\",\"name\":\"usdc\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RatioWith6Decimals\",\"name\":\"newMarkupFee\",\"type\":\"uint256\"}],\"name\":\"setMarkupFee\",\"outputs\":[{\"internalType\":\"RatioWith6Decimals\",\"name\":\"prevMarkupFee\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakedBalance\",\"outputs\":[{\"internalType\":\"LpQuantity\",\"name\":\"lpAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakedTokens\",\"outputs\":[{\"internalType\":\"UsdcQuantity\",\"name\":\"usdcAmount\",\"type\":\"uint256\"},{\"internalType\":\"MaiQuantity\",\"name\":\"maiAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakedValue\",\"outputs\":[{\"internalType\":\"UsdcQuantity\",\"name\":\"usdcAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"swapFee\",\"outputs\":[{\"internalType\":\"RatioWith6Decimals\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usdcAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usdcPrice\",\"outputs\":[{\"internalType\":\"PePerUsdcQuantity\",\"name\":\"price\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"PeQuantity\",\"name\":\"peAmount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"UsdcQuantity\",\"name\":\"usdcTotal\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"PeQuantity\",\"name\":\"peAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[{\"internalType\":\"LpQuantity\",\"name\":\"lpAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"See {IERC20Permit-DOMAIN_SEPARATOR}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"burn(uint256)\":{\"details\":\"Destroys `amount` tokens from the caller. See {ERC20-_burn}.\"},\"burnFrom(address,uint256)\":{\"details\":\"Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.\"},\"buyingPrice()\":{\"returns\":{\"price\":\" Minting price in USDC tokens per PE token\"}},\"collateralRatio()\":{\"returns\":{\"ratio\":\" Ratio of USDC tokens per PE token, with `_decimal` decimals\"}},\"compoundRewards()\":{\"custom:emit\":\"CompoundRewards\",\"returns\":{\"lpAmount\":\" The number of LP USDC/MAI tokens being put on stake\",\"usdcAmount\":\" The number of USDC tokens being re-invested\"}},\"constructor\":{\"params\":{\"_lpAddress\":\"LP Address for MAI/USDC\",\"_maiAddress\":\"Address used for the MAI tokens in vault\",\"_qiAddress\":\"Address used for the QI tokens in vault\",\"_qiDaoFarmAddress\":\"Address of the QiDao Farm to use\",\"_qiDaoPoolId\":\"Pool ID within the QiDao Farm\",\"_quickSwapRouterAddress\":\"Address of the QuickSwap Router to talk to\",\"_usdcAddress\":\"Address used for the USDC tokens in vault\"}},\"decimals()\":{\"returns\":{\"decimals_\":\" This will always be 6\"}},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"getLpReserves()\":{\"returns\":{\"maiReserves\":\" Number of MAI tokens in reserve\",\"usdcReserves\":\" Number of USDC tokens in reserve\"}},\"getPendingRewardsAmount()\":{\"returns\":{\"qiAmount\":\" Number of QI tokens accrued\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"initialize(uint256,uint256)\":{\"custom:emit\":\"Initialized\",\"params\":{\"startingRatio\":\"Initial minting ratio in PE tokens per USDC tokens minted (including DECIMALS)\",\"usdcAmount\":\"Number of collateral USDC tokens\"}},\"mint(address,uint256,uint256)\":{\"custom:emit\":\"Minted\",\"params\":{\"minReceive\":\"The minimum number of PE tokens to mint\",\"to\":\"The address to transfer the minted PE tokens to\",\"usdcAmount\":\"Number of USDC tokens to use as collateral\"},\"returns\":{\"peAmount\":\" The number of PE tokens actually minted\"}},\"mintForMigration(address,uint256,uint256)\":{\"custom:emit\":\"Minted\",\"params\":{\"minReceive\":\"The minimum number of PE tokens to mint\",\"to\":\"The address to transfer the minted PE tokens to\",\"usdcAmount\":\"Number of USDC tokens to use as collateral\"},\"returns\":{\"peAmount\":\" The number of PE tokens actually minted\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"See {IERC20Permit-nonces}.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"See {IERC20Permit-permit}.\"},\"quoteIn(uint256)\":{\"details\":\"This method was obtained by _inlining_ the call to mint() across contracts, and cleaning up the result.\",\"params\":{\"usdc\":\"Number of USDC tokens to quote for\"},\"returns\":{\"pe\":\" Number of PE tokens quoted for the given number of USDC tokens\"}},\"quoteOut(uint256)\":{\"details\":\"This method was obtained by _inlining_ the call to withdraw() across contracts, and cleaning up the result.\",\"params\":{\"pe\":\"Number of PE tokens to quote for\"},\"returns\":{\"usdc\":\" Number of USDC tokens quoted for the given number of PE tokens\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"setMarkupFee(uint256)\":{\"custom:emit\":\"MarkupFeeUpdated\",\"params\":{\"newMarkupFee\":\"New markup fee value\"},\"returns\":{\"prevMarkupFee\":\" Previous markup fee value\"}},\"stakedBalance()\":{\"returns\":{\"lpAmount\":\" Number of LP USDC/MAI token on stake\"}},\"stakedTokens()\":{\"returns\":{\"maiAmount\":\" Number of MAI tokens on stake\",\"usdcAmount\":\" Number of USDC tokens on stake\"}},\"stakedValue()\":{\"returns\":{\"usdcAmount\":\" Total equivalent number of USDC token on stake\"}},\"supportsInterface(bytes4)\":{\"params\":{\"interfaceId\":\"Interface ID to check against\"},\"returns\":{\"_0\":\"Whether the provided interface ID is supported\"}},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"},\"usdcPrice()\":{\"returns\":{\"price\":\" Collateralized price in USDC tokens per PE token\"}},\"withdraw(address,uint256)\":{\"custom:emit\":\"Withdrawal\",\"params\":{\"peAmount\":\"Number of PE tokens to withdraw\",\"to\":\"Address to deposit extracted USDC tokens into\"},\"returns\":{\"usdcTotal\":\" Number of USDC tokens extracted\"}},\"withdrawLiquidity(address,uint256)\":{\"custom:emit\":\"LiquidityWithdrawal\",\"params\":{\"peAmount\":\"Number of PE tokens to withdraw liquidity for\",\"to\":\"Address to deposit extracted LP USDC/MAI tokens into\"},\"returns\":{\"lpAmount\":\" Number of LP USDC/MAI tokens extracted\"}}},\"stateVariables\":{\"MARKUP_ROLE\":{\"return\":\" The role hash in question\",\"returns\":{\"_0\":\" The role hash in question\"}},\"MIGRATOR_ROLE\":{\"return\":\" The role hash in question\",\"returns\":{\"_0\":\" The role hash in question\"}},\"REWARDS_ROLE\":{\"return\":\" The role hash in question\",\"returns\":{\"_0\":\" The role hash in question\"}},\"initialized\":{\"return\":\"True whenever the contract has already been initialized, false otherwise\",\"returns\":{\"_0\":\"True whenever the contract has already been initialized, false otherwise\"}},\"lpAddress\":{\"return\":\"The address in question\",\"returns\":{\"_0\":\"The address in question\"}},\"maiAddress\":{\"return\":\"The address in question\",\"returns\":{\"_0\":\"The address in question\"}},\"markupFee\":{\"return\":\"The markup fee to use\",\"returns\":{\"_0\":\"The markup fee to use\"}},\"qiAddress\":{\"return\":\"The address in question\",\"returns\":{\"_0\":\"The address in question\"}},\"qiDaoFarmAddress\":{\"return\":\"The address in question\",\"returns\":{\"_0\":\"The address in question\"}},\"qiDaoPoolId\":{\"return\":\"The pool ID in question\",\"returns\":{\"_0\":\"The pool ID in question\"}},\"quickSwapRouterAddress\":{\"return\":\"The address in question\",\"returns\":{\"_0\":\"The address in question\"}},\"swapFee\":{\"return\":\"The swap fee to use\",\"returns\":{\"_0\":\"The swap fee to use\"}},\"usdcAddress\":{\"return\":\"The address in question\",\"returns\":{\"_0\":\"The address in question\"}}},\"version\":1},\"userdoc\":{\"events\":{\"CompoundRewards(uint256,uint256,uint256)\":{\"notice\":\"Emitted upon compounding rewards from QiDao's Farm back into the vault\"},\"Initialized(address,uint256,uint256)\":{\"notice\":\"Emitted upon initialization of the Peronio contract\"},\"LiquidityWithdrawal(address,uint256,uint256)\":{\"notice\":\"Emitted upon liquidity withdrawal\"},\"MarkupFeeUpdated(address,uint256)\":{\"notice\":\"Emitted upon the markup fee being updated\"},\"Minted(address,uint256,uint256)\":{\"notice\":\"Emitted upon minting PE tokens\"},\"Withdrawal(address,uint256,uint256)\":{\"notice\":\"Emitted upon collateral withdrawal\"}},\"kind\":\"user\",\"methods\":{\"MARKUP_ROLE()\":{\"notice\":\"Return the hash identifying the role responsible for updating the markup fee\"},\"MIGRATOR_ROLE()\":{\"notice\":\"Return the hash identifying the role responsible for migrating between versions\"},\"REWARDS_ROLE()\":{\"notice\":\"Return the hash identifying the role responsible for compounding rewards\"},\"buyingPrice()\":{\"notice\":\"Return the effective _minting_ price in USDC tokens per PE token\"},\"collateralRatio()\":{\"notice\":\"Return the ratio of total number of USDC tokens per PE token\"},\"compoundRewards()\":{\"notice\":\"Claim QiDao's QI token rewards, and re-invest them in the QuickSwap liquidity pool and QiDao's Farm\"},\"constructor\":{\"notice\":\"Construct a new Peronio contract\"},\"decimals()\":{\"notice\":\"Return the number of decimals the PE token will work with\"},\"getLpReserves()\":{\"notice\":\"Return the USDC and MAI token reserves present in QuickSwap\"},\"getPendingRewardsAmount()\":{\"notice\":\"Return the rewards accrued by staking LP USDC/MAI tokens in QiDao's Farm (in QI tokens)\"},\"initialize(uint256,uint256)\":{\"notice\":\"Initialize the PE token by providing collateral USDC tokens - initial conversion rate will be set at the given starting ratio\"},\"initialized()\":{\"notice\":\"Return wether the Peronio contract has been initialized yet\"},\"lpAddress()\":{\"notice\":\"Return the address used for the LP USDC/MAI tokens in vault\"},\"maiAddress()\":{\"notice\":\"Return the address used for the MAI tokens in vault\"},\"markupFee()\":{\"notice\":\"Return the markup fee the use, using `_decimals()` decimals implicitly\"},\"mint(address,uint256,uint256)\":{\"notice\":\"Mint PE tokens using the provided USDC tokens as collateral\"},\"mintForMigration(address,uint256,uint256)\":{\"notice\":\"Mint PE tokens using the provided USDC tokens as collateral --- used by the migrators in order not to incur normal fees\"},\"qiAddress()\":{\"notice\":\"Return the address used for the QI tokens in vault\"},\"qiDaoFarmAddress()\":{\"notice\":\"Return the address of the QiDao Farm to use\"},\"qiDaoPoolId()\":{\"notice\":\"Return the pool ID within the QiDao Farm\"},\"quickSwapRouterAddress()\":{\"notice\":\"Return the address of the QuickSwap Router to talk to\"},\"quoteIn(uint256)\":{\"notice\":\"Retrieve the expected number of PE tokens corresponding to the given number of USDC tokens for minting.\"},\"quoteOut(uint256)\":{\"notice\":\"Retrieve the expected number of USDC tokens corresponding to the given number of PE tokens for withdrawal.\"},\"setMarkupFee(uint256)\":{\"notice\":\"Set the markup fee to the given value (take into account that this will use `DECIMALS` decimals implicitly)\"},\"stakedBalance()\":{\"notice\":\"Return the number of LP USDC/MAI tokens on stake at QiDao's Farm\"},\"stakedTokens()\":{\"notice\":\"Return the number of USDC and MAI tokens on stake at QiDao's Farm\"},\"stakedValue()\":{\"notice\":\"Return the equivalent number of USDC tokens on stake at QiDao's Farm\"},\"supportsInterface(bytes4)\":{\"notice\":\"Implementation of the IERC165 interface\"},\"swapFee()\":{\"notice\":\"Return the swap fee the use, using `_decimals()` decimals implicitly\"},\"usdcAddress()\":{\"notice\":\"Return the address used for the USDC tokens in vault\"},\"usdcPrice()\":{\"notice\":\"Return the _collateralized_ price in USDC tokens per PE token\"},\"withdraw(address,uint256)\":{\"notice\":\"Extract the given number of PE tokens as USDC tokens\"},\"withdrawLiquidity(address,uint256)\":{\"notice\":\"Extract the given number of PE tokens as LP USDC/MAI tokens\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Peronio.sol\":\"Peronio\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":2000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/introspection/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 \\\"./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) public view virtual override returns (bool) {\\n        return interfaceId == type(IERC165).interfaceId;\\n    }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/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\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/access/AccessControl.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 \\\"./IAccessControl.sol\\\";\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/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);\\n        _;\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n    }\\n\\n    /**\\n     * @dev Returns `true` if `account` has been granted `role`.\\n     */\\n    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\\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                        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) public view virtual override returns (bytes32) {\\n        return _roles[role].adminRole;\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     *\\n     * May emit a {RoleGranted} event.\\n     */\\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n        _grantRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     *\\n     * May emit a {RoleRevoked} event.\\n     */\\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n        _revokeRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from the calling account.\\n     *\\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n     * purpose is to provide a mechanism for accounts to lose their privileges\\n     * if they are compromised (such as when a trusted device is misplaced).\\n     *\\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must be `account`.\\n     *\\n     * May emit a {RoleRevoked} event.\\n     */\\n    function renounceRole(bytes32 role, address account) public virtual override {\\n        require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\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\",\"keccak256\":\"0x5b35d8e68aeaccc685239bd9dd79b9ba01a0357930f8a3307ab85511733d9724\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/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(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n    /**\\n     * @dev Emitted when `account` is granted `role`.\\n     *\\n     * `sender` is the account that originated the contract call, an admin role\\n     * bearer except when using {AccessControl-_setupRole}.\\n     */\\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n    /**\\n     * @dev Emitted when `account` is revoked `role`.\\n     *\\n     * `sender` is the account that originated the contract call:\\n     *   - if using `revokeRole`, it is the admin role bearer\\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n     */\\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n    /**\\n     * @dev Returns `true` if `account` has been granted `role`.\\n     */\\n    function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n    /**\\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\\n     * {revokeRole}.\\n     *\\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n     */\\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     */\\n    function grantRole(bytes32 role, address account) external;\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     */\\n    function revokeRole(bytes32 role, address account) external;\\n\\n    /**\\n     * @dev Revokes `role` from the calling account.\\n     *\\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n     * purpose is to provide a mechanism for accounts to lose their privileges\\n     * if they are compromised (such as when a trusted device is misplaced).\\n     *\\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must be `account`.\\n     */\\n    function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/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\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n    mapping(address => uint256) private _balances;\\n\\n    mapping(address => mapping(address => uint256)) private _allowances;\\n\\n    uint256 private _totalSupply;\\n\\n    string private _name;\\n    string private _symbol;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}.\\n     *\\n     * The default value of {decimals} is 18. To select a different value for\\n     * {decimals} you should overload it.\\n     *\\n     * All two of these values are immutable: they can only be set once during\\n     * construction.\\n     */\\n    constructor(string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev Returns the symbol of the token, usually a shorter version of the\\n     * name.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev Returns the number of decimals used to get its user representation.\\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n     *\\n     * Tokens usually opt for a value of 18, imitating the relationship between\\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n     * overridden;\\n     *\\n     * NOTE: This information is only used for _display_ purposes: it in\\n     * no way affects any of the arithmetic of the contract, including\\n     * {IERC20-balanceOf} and {IERC20-transfer}.\\n     */\\n    function decimals() public view virtual override returns (uint8) {\\n        return 18;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        return _totalSupply;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-balanceOf}.\\n     */\\n    function balanceOf(address account) public view virtual override returns (uint256) {\\n        return _balances[account];\\n    }\\n\\n    /**\\n     * @dev See {IERC20-transfer}.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n        address owner = _msgSender();\\n        _transfer(owner, to, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-allowance}.\\n     */\\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n        return _allowances[owner][spender];\\n    }\\n\\n    /**\\n     * @dev See {IERC20-approve}.\\n     *\\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        address owner = _msgSender();\\n        _approve(owner, spender, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-transferFrom}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance. This is not\\n     * required by the EIP. See the note at the beginning of {ERC20}.\\n     *\\n     * NOTE: Does not update the allowance if the current allowance\\n     * is the maximum `uint256`.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` and `to` cannot be the zero address.\\n     * - `from` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``from``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) public virtual override returns (bool) {\\n        address spender = _msgSender();\\n        _spendAllowance(from, spender, amount);\\n        _transfer(from, to, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\\n     *\\n     * This is an alternative to {approve} that can be used as a mitigation for\\n     * problems described in {IERC20-approve}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n        address owner = _msgSender();\\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n     *\\n     * This is an alternative to {approve} that can be used as a mitigation for\\n     * problems described in {IERC20-approve}.\\n     *\\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\\n     * `subtractedValue`.\\n     */\\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n        address owner = _msgSender();\\n        uint256 currentAllowance = allowance(owner, spender);\\n        require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n        unchecked {\\n            _approve(owner, spender, currentAllowance - subtractedValue);\\n        }\\n\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves `amount` of tokens from `from` to `to`.\\n     *\\n     * This internal function is equivalent to {transfer}, and can be used to\\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\\n     *\\n     * Emits a {Transfer} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `from` must have a balance of at least `amount`.\\n     */\\n    function _transfer(\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) internal virtual {\\n        require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, amount);\\n\\n        uint256 fromBalance = _balances[from];\\n        require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        unchecked {\\n            _balances[from] = fromBalance - amount;\\n        }\\n        _balances[to] += amount;\\n\\n        emit Transfer(from, to, amount);\\n\\n        _afterTokenTransfer(from, to, amount);\\n    }\\n\\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n     * the total supply.\\n     *\\n     * Emits a {Transfer} event with `from` set to the zero address.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     */\\n    function _mint(address account, uint256 amount) internal virtual {\\n        require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n        _beforeTokenTransfer(address(0), account, amount);\\n\\n        _totalSupply += amount;\\n        _balances[account] += amount;\\n        emit Transfer(address(0), account, amount);\\n\\n        _afterTokenTransfer(address(0), account, amount);\\n    }\\n\\n    /**\\n     * @dev Destroys `amount` tokens from `account`, reducing the\\n     * total supply.\\n     *\\n     * Emits a {Transfer} event with `to` set to the zero address.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     * - `account` must have at least `amount` tokens.\\n     */\\n    function _burn(address account, uint256 amount) internal virtual {\\n        require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n        _beforeTokenTransfer(account, address(0), amount);\\n\\n        uint256 accountBalance = _balances[account];\\n        require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        unchecked {\\n            _balances[account] = accountBalance - amount;\\n        }\\n        _totalSupply -= amount;\\n\\n        emit Transfer(account, address(0), amount);\\n\\n        _afterTokenTransfer(account, address(0), amount);\\n    }\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n     *\\n     * This internal function is equivalent to `approve`, and can be used to\\n     * e.g. set automatic allowances for certain subsystems, etc.\\n     *\\n     * Emits an {Approval} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `owner` cannot be the zero address.\\n     * - `spender` cannot be the zero address.\\n     */\\n    function _approve(\\n        address owner,\\n        address spender,\\n        uint256 amount\\n    ) internal virtual {\\n        require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n        require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n        _allowances[owner][spender] = amount;\\n        emit Approval(owner, spender, amount);\\n    }\\n\\n    /**\\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n     *\\n     * Does not update the allowance amount in case of infinite allowance.\\n     * Revert if not enough allowance is available.\\n     *\\n     * Might emit an {Approval} event.\\n     */\\n    function _spendAllowance(\\n        address owner,\\n        address spender,\\n        uint256 amount\\n    ) internal virtual {\\n        uint256 currentAllowance = allowance(owner, spender);\\n        if (currentAllowance != type(uint256).max) {\\n            require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n            unchecked {\\n                _approve(owner, spender, currentAllowance - amount);\\n            }\\n        }\\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 amount\\n    ) internal virtual {}\\n\\n    /**\\n     * @dev Hook that is called after 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     * has been transferred to `to`.\\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens have been 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 _afterTokenTransfer(\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/token/ERC20/IERC20.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 IERC20 {\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n    /**\\n     * @dev Returns the 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) external view 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\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n    /**\\n     * @dev Destroys `amount` tokens from the caller.\\n     *\\n     * See {ERC20-_burn}.\\n     */\\n    function burn(uint256 amount) public virtual {\\n        _burn(_msgSender(), amount);\\n    }\\n\\n    /**\\n     * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n     * allowance.\\n     *\\n     * See {ERC20-_burn} and {ERC20-allowance}.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have allowance for ``accounts``'s tokens of at least\\n     * `amount`.\\n     */\\n    function burnFrom(address account, uint256 amount) public virtual {\\n        _spendAllowance(account, _msgSender(), amount);\\n        _burn(account, amount);\\n    }\\n}\\n\",\"keccak256\":\"0x0d19410453cda55960a818e02bd7c18952a5c8fe7a3036e81f0d599f34487a7b\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/token/ERC20/extensions/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 \\\"../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\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/token/ERC20/extensions/draft-ERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./draft-IERC20Permit.sol\\\";\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"../../../utils/cryptography/ECDSA.sol\\\";\\nimport \\\"../../../utils/Counters.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n *\\n * _Available since v3.4._\\n */\\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\\n    using Counters for Counters.Counter;\\n\\n    mapping(address => Counters.Counter) private _nonces;\\n\\n    // solhint-disable-next-line var-name-mixedcase\\n    bytes32 private constant _PERMIT_TYPEHASH =\\n        keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n    /**\\n     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\\n     * However, to ensure consistency with the upgradeable transpiler, we will continue\\n     * to reserve a slot.\\n     * @custom:oz-renamed-from _PERMIT_TYPEHASH\\n     */\\n    // solhint-disable-next-line var-name-mixedcase\\n    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\\n\\n    /**\\n     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n     *\\n     * It's a good idea to use the same `name` that is defined as the ERC20 token name.\\n     */\\n    constructor(string memory name) EIP712(name, \\\"1\\\") {}\\n\\n    /**\\n     * @dev See {IERC20Permit-permit}.\\n     */\\n    function permit(\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) public virtual override {\\n        require(block.timestamp <= deadline, \\\"ERC20Permit: expired deadline\\\");\\n\\n        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n\\n        address signer = ECDSA.recover(hash, v, r, s);\\n        require(signer == owner, \\\"ERC20Permit: invalid signature\\\");\\n\\n        _approve(owner, spender, value);\\n    }\\n\\n    /**\\n     * @dev See {IERC20Permit-nonces}.\\n     */\\n    function nonces(address owner) public view virtual override returns (uint256) {\\n        return _nonces[owner].current();\\n    }\\n\\n    /**\\n     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view override returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev \\\"Consume a nonce\\\": return the current value and increment.\\n     *\\n     * _Available since v4.1._\\n     */\\n    function _useNonce(address owner) internal virtual returns (uint256 current) {\\n        Counters.Counter storage nonce = _nonces[owner];\\n        current = nonce.current();\\n        nonce.increment();\\n    }\\n}\\n\",\"keccak256\":\"0x07536242e24ee7067295d32c08e495a33e605f3c52f8ee4ec3bdcb7a351313d2\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n    /**\\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n     * given ``owner``'s signed approval.\\n     *\\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n     * ordering also apply here.\\n     *\\n     * Emits an {Approval} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     * - `deadline` must be a timestamp in the future.\\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n     * over the EIP712-formatted function arguments.\\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\\n     *\\n     * For more information on the signature format, see the\\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n     * section].\\n     */\\n    function permit(\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external;\\n\\n    /**\\n     * @dev Returns the current nonce for `owner`. This value must be\\n     * included whenever a signature is generated for {permit}.\\n     *\\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n     * prevents a signature from being used multiple times.\\n     */\\n    function nonces(address owner) external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n    using Address for address;\\n\\n    function safeTransfer(\\n        IERC20 token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(\\n        IERC20 token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n    }\\n\\n    /**\\n     * @dev Deprecated. This function has issues similar to the ones found in\\n     * {IERC20-approve}, and its usage is discouraged.\\n     *\\n     * Whenever possible, use {safeIncreaseAllowance} and\\n     * {safeDecreaseAllowance} instead.\\n     */\\n    function safeApprove(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        // safeApprove should only be called when setting an initial allowance,\\n        // or when resetting it to zero. To increase and decrease it, use\\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n        require(\\n            (value == 0) || (token.allowance(address(this), spender) == 0),\\n            \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n        );\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n    }\\n\\n    function safeIncreaseAllowance(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        unchecked {\\n            uint256 oldAllowance = token.allowance(address(this), spender);\\n            require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n            uint256 newAllowance = oldAllowance - value;\\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n        }\\n    }\\n\\n    function safePermit(\\n        IERC20Permit token,\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) internal {\\n        uint256 nonceBefore = token.nonces(owner);\\n        token.permit(owner, spender, value, deadline, v, r, s);\\n        uint256 nonceAfter = token.nonces(owner);\\n        require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     * @param token The token targeted by the call.\\n     * @param data The call data (encoded using abi.encode or one of its variants).\\n     */\\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n        // the target address contains contract code and also asserts for success in the low-level call.\\n\\n        bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n        if (returndata.length > 0) {\\n            // Return data is optional\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/utils/Address.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 Address {\\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(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\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) internal returns (bytes memory) {\\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 functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\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(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\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) internal view returns (bytes memory) {\\n        return 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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.delegatecall(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\",\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/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\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/utils/Counters.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n */\\nlibrary Counters {\\n    struct Counter {\\n        // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n        // this feature: see https://github.com/ethereum/solidity/issues/4637\\n        uint256 _value; // default: 0\\n    }\\n\\n    function current(Counter storage counter) internal view returns (uint256) {\\n        return counter._value;\\n    }\\n\\n    function increment(Counter storage counter) internal {\\n        unchecked {\\n            counter._value += 1;\\n        }\\n    }\\n\\n    function decrement(Counter storage counter) internal {\\n        uint256 value = counter._value;\\n        require(value > 0, \\\"Counter: decrement overflow\\\");\\n        unchecked {\\n            counter._value = value - 1;\\n        }\\n    }\\n\\n    function reset(Counter storage counter) internal {\\n        counter._value = 0;\\n    }\\n}\\n\",\"keccak256\":\"0xf0018c2440fbe238dd3a8732fa8e17a0f9dce84d31451dc8a32f6d62b349c9f1\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/utils/Strings.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 Strings {\\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) internal pure returns (string memory) {\\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\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    enum RecoverError {\\n        NoError,\\n        InvalidSignature,\\n        InvalidSignatureLength,\\n        InvalidSignatureS,\\n        InvalidSignatureV\\n    }\\n\\n    function _throwError(RecoverError error) private pure {\\n        if (error == RecoverError.NoError) {\\n            return; // no error: do nothing\\n        } else if (error == RecoverError.InvalidSignature) {\\n            revert(\\\"ECDSA: invalid signature\\\");\\n        } else if (error == RecoverError.InvalidSignatureLength) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        } else if (error == RecoverError.InvalidSignatureS) {\\n            revert(\\\"ECDSA: invalid signature 's' value\\\");\\n        } else if (error == RecoverError.InvalidSignatureV) {\\n            revert(\\\"ECDSA: invalid signature 'v' value\\\");\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature` or error string. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     *\\n     * Documentation for signature generation:\\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n     *\\n     * _Available since v4.3._\\n     */\\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n        // Check the signature length\\n        // - case 65: r,s,v signature (standard)\\n        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\\n        if (signature.length == 65) {\\n            bytes32 r;\\n            bytes32 s;\\n            uint8 v;\\n            // ecrecover takes the signature parameters, and the only way to get them\\n            // currently is to use assembly.\\n            /// @solidity memory-safe-assembly\\n            assembly {\\n                r := mload(add(signature, 0x20))\\n                s := mload(add(signature, 0x40))\\n                v := byte(0, mload(add(signature, 0x60)))\\n            }\\n            return tryRecover(hash, v, r, s);\\n        } else if (signature.length == 64) {\\n            bytes32 r;\\n            bytes32 vs;\\n            // ecrecover takes the signature parameters, and the only way to get them\\n            // currently is to use assembly.\\n            /// @solidity memory-safe-assembly\\n            assembly {\\n                r := mload(add(signature, 0x20))\\n                vs := mload(add(signature, 0x40))\\n            }\\n            return tryRecover(hash, r, vs);\\n        } else {\\n            return (address(0), RecoverError.InvalidSignatureLength);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\\n        _throwError(error);\\n        return recovered;\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n     *\\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n     *\\n     * _Available since v4.3._\\n     */\\n    function tryRecover(\\n        bytes32 hash,\\n        bytes32 r,\\n        bytes32 vs\\n    ) internal pure returns (address, RecoverError) {\\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\\n        return tryRecover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n     *\\n     * _Available since v4.2._\\n     */\\n    function recover(\\n        bytes32 hash,\\n        bytes32 r,\\n        bytes32 vs\\n    ) internal pure returns (address) {\\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n        _throwError(error);\\n        return recovered;\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     *\\n     * _Available since v4.3._\\n     */\\n    function tryRecover(\\n        bytes32 hash,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) internal pure returns (address, RecoverError) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n            return (address(0), RecoverError.InvalidSignatureS);\\n        }\\n        if (v != 27 && v != 28) {\\n            return (address(0), RecoverError.InvalidSignatureV);\\n        }\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        if (signer == address(0)) {\\n            return (address(0), RecoverError.InvalidSignature);\\n        }\\n\\n        return (signer, RecoverError.NoError);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(\\n        bytes32 hash,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) internal pure returns (address) {\\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n        _throwError(error);\\n        return recovered;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * produces hash corresponding to the one signed with the\\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n     * JSON-RPC method as part of EIP-191.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\\n     * produces hash corresponding to the one signed with the\\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n     * JSON-RPC method as part of EIP-191.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Typed Data, created from a\\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\\n     * to the one signed with the\\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n     * JSON-RPC method as part of EIP-712.\\n     *\\n     * See {recover}.\\n     */\\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n    }\\n}\\n\",\"keccak256\":\"0x84ac2d2f343df1e683da7a12bbcf70db542a7a7a0cea90a5d70fcb5e5d035481\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n    address private immutable _CACHED_THIS;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\n            \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n        );\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = block.chainid;\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _CACHED_THIS = address(this);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view returns (bytes32) {\\n        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(\\n        bytes32 typeHash,\\n        bytes32 nameHash,\\n        bytes32 versionHash\\n    ) private view returns (bytes32) {\\n        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n    }\\n}\\n\",\"keccak256\":\"0x6688fad58b9ec0286d40fa957152e575d5d8bd4c3aa80985efdb11b44f776ae7\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/utils/introspection/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 \\\"./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) public view virtual override returns (bool) {\\n        return interfaceId == type(IERC165).interfaceId;\\n    }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/utils/introspection/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\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts_latest/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n    enum Rounding {\\n        Down, // Toward negative infinity\\n        Up, // Toward infinity\\n        Zero // Toward zero\\n    }\\n\\n    /**\\n     * @dev Returns the largest of two numbers.\\n     */\\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a >= b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the smallest of two numbers.\\n     */\\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a < b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the average of two numbers. The result is rounded towards\\n     * zero.\\n     */\\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // (a + b) / 2 can overflow.\\n        return (a & b) + (a ^ b) / 2;\\n    }\\n\\n    /**\\n     * @dev Returns the ceiling of the division of two numbers.\\n     *\\n     * This differs from standard division with `/` in that it rounds up instead\\n     * of rounding down.\\n     */\\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // (a + b - 1) / b can overflow on addition, so we distribute.\\n        return a == 0 ? 0 : (a - 1) / b + 1;\\n    }\\n\\n    /**\\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n     * with further edits by Uniswap Labs also under MIT license.\\n     */\\n    function mulDiv(\\n        uint256 x,\\n        uint256 y,\\n        uint256 denominator\\n    ) internal pure returns (uint256 result) {\\n        unchecked {\\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n            // variables such that product = prod1 * 2^256 + prod0.\\n            uint256 prod0; // Least significant 256 bits of the product\\n            uint256 prod1; // Most significant 256 bits of the product\\n            assembly {\\n                let mm := mulmod(x, y, not(0))\\n                prod0 := mul(x, y)\\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n            }\\n\\n            // Handle non-overflow cases, 256 by 256 division.\\n            if (prod1 == 0) {\\n                return prod0 / denominator;\\n            }\\n\\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n            require(denominator > prod1);\\n\\n            ///////////////////////////////////////////////\\n            // 512 by 256 division.\\n            ///////////////////////////////////////////////\\n\\n            // Make division exact by subtracting the remainder from [prod1 prod0].\\n            uint256 remainder;\\n            assembly {\\n                // Compute remainder using mulmod.\\n                remainder := mulmod(x, y, denominator)\\n\\n                // Subtract 256 bit number from 512 bit number.\\n                prod1 := sub(prod1, gt(remainder, prod0))\\n                prod0 := sub(prod0, remainder)\\n            }\\n\\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n            // See https://cs.stackexchange.com/q/138556/92363.\\n\\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\\n            uint256 twos = denominator & (~denominator + 1);\\n            assembly {\\n                // Divide denominator by twos.\\n                denominator := div(denominator, twos)\\n\\n                // Divide [prod1 prod0] by twos.\\n                prod0 := div(prod0, twos)\\n\\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n                twos := add(div(sub(0, twos), twos), 1)\\n            }\\n\\n            // Shift in bits from prod1 into prod0.\\n            prod0 |= prod1 * twos;\\n\\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n            // four bits. That is, denominator * inv = 1 mod 2^4.\\n            uint256 inverse = (3 * denominator) ^ 2;\\n\\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n            // in modular arithmetic, doubling the correct bits in each step.\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n            // is no longer required.\\n            result = prod0 * inverse;\\n            return result;\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n     */\\n    function mulDiv(\\n        uint256 x,\\n        uint256 y,\\n        uint256 denominator,\\n        Rounding rounding\\n    ) internal pure returns (uint256) {\\n        uint256 result = mulDiv(x, y, denominator);\\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n            result += 1;\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\\n     *\\n     * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n     */\\n    function sqrt(uint256 a) internal pure returns (uint256) {\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n        // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n        // `msb(a) <= a < 2*msb(a)`.\\n        // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\\n        // This gives `2**k < a <= 2**(k+1)` \\u2192 `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\\n        // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\\n        // good first aproximation of `sqrt(a)` with at least 1 correct bit.\\n        uint256 result = 1;\\n        uint256 x = a;\\n        if (x >> 128 > 0) {\\n            x >>= 128;\\n            result <<= 64;\\n        }\\n        if (x >> 64 > 0) {\\n            x >>= 64;\\n            result <<= 32;\\n        }\\n        if (x >> 32 > 0) {\\n            x >>= 32;\\n            result <<= 16;\\n        }\\n        if (x >> 16 > 0) {\\n            x >>= 16;\\n            result <<= 8;\\n        }\\n        if (x >> 8 > 0) {\\n            x >>= 8;\\n            result <<= 4;\\n        }\\n        if (x >> 4 > 0) {\\n            x >>= 4;\\n            result <<= 2;\\n        }\\n        if (x >> 2 > 0) {\\n            result <<= 1;\\n        }\\n\\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n        // into the expected uint128 result.\\n        unchecked {\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            return min(result, a / result);\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates sqrt(a), following the selected rounding direction.\\n     */\\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n        uint256 result = sqrt(a);\\n        if (rounding == Rounding.Up && result * result < a) {\\n            result += 1;\\n        }\\n        return result;\\n    }\\n}\\n\",\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\"},\"contracts/IPeronio.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n/**\\n * Type representing an USDC token quantity\\n *\\n */\\ntype UsdcQuantity is uint256;\\n\\n/**\\n * Type representing a MAI token quantity\\n *\\n */\\ntype MaiQuantity is uint256;\\n\\n/**\\n * Type representing an LP USDC/MAI token quantity\\n *\\n */\\ntype LpQuantity is uint256;\\n\\n/**\\n * Type representing a PE token quantity\\n *\\n */\\ntype PeQuantity is uint256;\\n\\n/**\\n * Type representing a QI token quantity\\n *\\n */\\ntype QiQuantity is uint256;\\n\\n/**\\n * Type representing a ratio of PE/USD tokens (always represented using `DECIMALS` decimals)\\n *\\n */\\ntype PePerUsdcQuantity is uint256;\\n\\n/**\\n * Type representing a ratio of USD/PE tokens (always represented using `DECIMALS` decimals)\\n *\\n */\\ntype UsdcPerPeQuantity is uint256;\\n\\n/**\\n * Type representing an adimensional ratio, expressed with 6 decimals\\n *\\n */\\ntype RatioWith6Decimals is uint256;\\n\\n/**\\n * Type representing a role ID\\n *\\n */\\ntype RoleId is bytes32;\\n\\ninterface IPeronio {\\n    // --- Events ---------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Emitted upon initialization of the Peronio contract\\n     *\\n     * @param owner  The address initializing the contract\\n     * @param collateral  The number of USDC tokens used as collateral\\n     * @param startingRatio  The number of PE tokens per USDC token the vault is initialized with\\n     */\\n    event Initialized(address owner, UsdcQuantity collateral, PePerUsdcQuantity startingRatio);\\n\\n    /**\\n     * Emitted upon minting PE tokens\\n     *\\n     * @param to  The address where minted PE tokens get transferred to\\n     * @param collateralAmount  The number of USDC tokens used as collateral in this minting\\n     * @param tokenAmount  Amount of PE tokens minted\\n     */\\n    event Minted(address indexed to, UsdcQuantity collateralAmount, PeQuantity tokenAmount);\\n\\n    /**\\n     * Emitted upon collateral withdrawal\\n     *\\n     * @param to  Address where the USDC token withdrawal is directed\\n     * @param collateralAmount  The number of USDC tokens withdrawn\\n     * @param tokenAmount  The number of PE tokens burnt\\n     */\\n    event Withdrawal(address indexed to, UsdcQuantity collateralAmount, PeQuantity tokenAmount);\\n\\n    /**\\n     * Emitted upon liquidity withdrawal\\n     *\\n     * @param to  Address where the USDC token withdrawal is directed\\n     * @param lpAmount  The number of LP USDC/MAI tokens withdrawn\\n     * @param tokenAmount  The number of PE tokens burnt\\n     */\\n    event LiquidityWithdrawal(address indexed to, LpQuantity lpAmount, PeQuantity tokenAmount);\\n\\n    /**\\n     * Emitted upon the markup fee being updated\\n     *\\n     * @param operator  Address of the one updating the markup fee\\n     * @param markupFee  New markup fee\\n     */\\n    event MarkupFeeUpdated(address operator, RatioWith6Decimals markupFee);\\n\\n    /**\\n     * Emitted upon compounding rewards from QiDao's Farm back into the vault\\n     *\\n     * @param qi  Number of awarded QI tokens\\n     * @param usdc  Equivalent number of USDC tokens\\n     * @param lp  Number of LP USDC/MAI tokens re-invested\\n     */\\n    event CompoundRewards(QiQuantity qi, UsdcQuantity usdc, LpQuantity lp);\\n\\n    // --- Roles - Automatic ----------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the hash identifying the role responsible for updating the markup fee\\n     *\\n     * @return roleId  The role hash in question\\n     */\\n    function MARKUP_ROLE() external view returns (RoleId roleId); // solhint-disable-line func-name-mixedcase\\n\\n    /**\\n     * Return the hash identifying the role responsible for compounding rewards\\n     *\\n     * @return roleId  The role hash in question\\n     */\\n    function REWARDS_ROLE() external view returns (RoleId roleId); // solhint-disable-line func-name-mixedcase\\n\\n    /**\\n     * Return the hash identifying the role responsible for migrating between versions\\n     *\\n     * @return roleId  The role hash in question\\n     */\\n    function MIGRATOR_ROLE() external view returns (RoleId roleId); // solhint-disable-line func-name-mixedcase\\n\\n    // --- Addresses - Automatic ------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the address used for the USDC tokens in vault\\n     *\\n     * @return  The address in question\\n     */\\n    function usdcAddress() external view returns (address);\\n\\n    /**\\n     * Return the address used for the MAI tokens in vault\\n     *\\n     * @return  The address in question\\n     */\\n    function maiAddress() external view returns (address);\\n\\n    /**\\n     * Return the address used for the LP USDC/MAI tokens in vault\\n     *\\n     * @return  The address in question\\n     */\\n    function lpAddress() external view returns (address);\\n\\n    /**\\n     * Return the address used for the QI tokens in vault\\n     *\\n     * @return  The address in question\\n     */\\n    function qiAddress() external view returns (address);\\n\\n    /**\\n     * Return the address of the QuickSwap Router to talk to\\n     *\\n     * @return  The address in question\\n     */\\n    function quickSwapRouterAddress() external view returns (address);\\n\\n    /**\\n     * Return the address of the QiDao Farm to use\\n     *\\n     * @return  The address in question\\n     */\\n    function qiDaoFarmAddress() external view returns (address);\\n\\n    /**\\n     * Return the pool ID within the QiDao Farm\\n     *\\n     * @return  The pool ID in question\\n     */\\n    function qiDaoPoolId() external view returns (uint256);\\n\\n    // --- Fees - Automatic -----------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the markup fee the use, using `_decimals()` decimals implicitly\\n     *\\n     * @return  The markup fee to use\\n     */\\n    function markupFee() external view returns (RatioWith6Decimals);\\n\\n    /**\\n     * Return the swap fee the use, using `_decimals()` decimals implicitly\\n     *\\n     * @return  The swap fee to use\\n     */\\n    function swapFee() external view returns (RatioWith6Decimals);\\n\\n    // --- Status - Automatic ---------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return wether the Peronio contract has been initialized yet\\n     *\\n     * @return  True whenever the contract has already been initialized, false otherwise\\n     */\\n    function initialized() external view returns (bool);\\n\\n    // --- Decimals -------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the number of decimals the PE token will work with\\n     *\\n     * @return decimals_  This will always be 6\\n     */\\n    function decimals() external view returns (uint8);\\n\\n    // --- Markup fee change ----------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Set the markup fee to the given value (take into account that this will use `_decimals` decimals implicitly)\\n     *\\n     * @param newMarkupFee  New markup fee value\\n     * @return prevMarkupFee  Previous markup fee value\\n     * @custom:emit  MarkupFeeUpdated\\n     */\\n    function setMarkupFee(RatioWith6Decimals newMarkupFee) external returns (RatioWith6Decimals prevMarkupFee);\\n\\n    // --- Initialization -------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Initialize the PE token by providing collateral USDC tokens - initial conversion rate will be set at the given starting ratio\\n     *\\n     * @param usdcAmount  Number of collateral USDC tokens\\n     * @param startingRatio  Initial minting ratio in PE tokens per USDC tokens minted\\n     * @custom:emit  Initialized\\n     */\\n    function initialize(UsdcQuantity usdcAmount, PePerUsdcQuantity startingRatio) external;\\n\\n    // --- State views ----------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the USDC and MAI token reserves present in QuickSwap\\n     *\\n     * @return usdcReserves  Number of USDC tokens in reserve\\n     * @return maiReserves  Number of MAI tokens in reserve\\n     */\\n    function getLpReserves() external view returns (UsdcQuantity usdcReserves, MaiQuantity maiReserves);\\n\\n    /**\\n     * Return the number of LP USDC/MAI tokens on stake at QiDao's Farm\\n     *\\n     * @return lpAmount  Number of LP USDC/MAI token on stake\\n     */\\n    function stakedBalance() external view returns (LpQuantity lpAmount);\\n\\n    /**\\n     * Return the number of USDC and MAI tokens on stake at QiDao's Farm\\n     *\\n     * @return usdcAmount  Number of USDC tokens on stake\\n     * @return maiAmount  Number of MAI tokens on stake\\n     */\\n    function stakedTokens() external view returns (UsdcQuantity usdcAmount, MaiQuantity maiAmount);\\n\\n    /**\\n     * Return the equivalent number of USDC tokens on stake at QiDao's Farm\\n     *\\n     * @return usdcAmount  Total equivalent number of USDC token on stake\\n     */\\n    function stakedValue() external view returns (UsdcQuantity usdcAmount);\\n\\n    /**\\n     * Return the _collateralized_ price in USDC tokens per PE token\\n     *\\n     * @return price  Collateralized price in USDC tokens per PE token\\n     */\\n    function usdcPrice() external view returns (PePerUsdcQuantity price);\\n\\n    /**\\n     * Return the effective _minting_ price in USDC tokens per PE token\\n     *\\n     * @return price  Minting price in USDC tokens per PE token\\n     */\\n    function buyingPrice() external view returns (UsdcPerPeQuantity price);\\n\\n    /**\\n     * Return the ratio of total number of USDC tokens per PE token\\n     *\\n     * @return ratio  Ratio of USDC tokens per PE token, with `_decimal` decimals\\n     */\\n    function collateralRatio() external view returns (UsdcPerPeQuantity ratio);\\n\\n    // --- State changers -------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Mint PE tokens using the provided USDC tokens as collateral --- used by the migrators in order not to incur normal fees\\n     *\\n     * @param to  The address to transfer the minted PE tokens to\\n     * @param usdcAmount  Number of USDC tokens to use as collateral\\n     * @param minReceive  The minimum number of PE tokens to mint\\n     * @return peAmount  The number of PE tokens actually minted\\n     * @custom:emit  Minted\\n     */\\n    function mintForMigration(\\n        address to,\\n        UsdcQuantity usdcAmount,\\n        PeQuantity minReceive\\n    ) external returns (PeQuantity peAmount);\\n\\n    /**\\n     * Mint PE tokens using the provided USDC tokens as collateral\\n     *\\n     * @param to  The address to transfer the minted PE tokens to\\n     * @param usdcAmount  Number of USDC tokens to use as collateral\\n     * @param minReceive  The minimum number of PE tokens to mint\\n     * @return peAmount  The number of PE tokens actually minted\\n     * @custom:emit  Minted\\n     */\\n    function mint(\\n        address to,\\n        UsdcQuantity usdcAmount,\\n        PeQuantity minReceive\\n    ) external returns (PeQuantity peAmount);\\n\\n    /**\\n     * Extract the given number of PE tokens as USDC tokens\\n     *\\n     * @param to  Address to deposit extracted USDC tokens into\\n     * @param peAmount  Number of PE tokens to withdraw\\n     * @return usdcTotal  Number of USDC tokens extracted\\n     * @custom:emit  Withdrawal\\n     */\\n    function withdraw(address to, PeQuantity peAmount) external returns (UsdcQuantity usdcTotal);\\n\\n    /**\\n     * Extract the given number of PE tokens as LP USDC/MAI tokens\\n     *\\n     * @param to  Address to deposit extracted LP USDC/MAI tokens into\\n     * @param peAmount  Number of PE tokens to withdraw liquidity for\\n     * @return lpAmount  Number of LP USDC/MAI tokens extracted\\n     * @custom:emit LiquidityWithdrawal\\n     */\\n    function withdrawLiquidity(address to, PeQuantity peAmount) external returns (LpQuantity lpAmount);\\n\\n    // --- Rewards --------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the rewards accrued by staking LP USDC/MAI tokens in QiDao's Farm (in QI tokens)\\n     *\\n     * @return qiAmount  Number of QI tokens accrued\\n     */\\n    function getPendingRewardsAmount() external view returns (QiQuantity qiAmount);\\n\\n    /**\\n     * Claim QiDao's QI token rewards, and re-invest them in the QuickSwap liquidity pool and QiDao's Farm\\n     *\\n     * @return usdcAmount  The number of USDC tokens being re-invested\\n     * @return lpAmount  The number of LP USDC/MAI tokens being put on stake\\n     * @custom:emit CompoundRewards\\n     */\\n    function compoundRewards() external returns (UsdcQuantity usdcAmount, LpQuantity lpAmount);\\n\\n    // --- Quotes ---------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Retrieve the expected number of PE tokens corresponding to the given number of USDC tokens for minting.\\n     *\\n     * @param usdc  Number of USDC tokens to quote for\\n     * @return pe  Number of PE tokens quoted for the given number of USDC tokens\\n     */\\n    function quoteIn(UsdcQuantity usdc) external view returns (PeQuantity pe);\\n\\n    /**\\n     * Retrieve the expected number of USDC tokens corresponding to the given number of PE tokens for withdrawal.\\n     *\\n     * @param pe  Number of PE tokens to quote for\\n     * @return usdc  Number of USDC tokens quoted for the given number of PE tokens\\n     */\\n    function quoteOut(PeQuantity pe) external view returns (UsdcQuantity usdc);\\n}\\n\",\"keccak256\":\"0x1d04021ebd684dbf1d61a6f9c475b14fdf90b5c9d88f77b4cff16f45f33fd669\",\"license\":\"MIT\"},\"contracts/IPeronioSupport.sol\":{\"content\":\"pragma solidity ^0.8.17;\\n\\n// SPDX-License-Identifier: MIT\\n\\nimport \\\"./IPeronio.sol\\\";\\n\\nimport {Math} from \\\"@openzeppelin/contracts_latest/utils/math/Math.sol\\\";\\n\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n// --- Standard Numeric Types ---------------------------------------------------------------------------------------------------------------------------------\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n//\\n// Standard Numeric Types (SNTs) can be operated with in the same manner as \\\"normal\\\" numeric types can.\\n// This means that SNTs can:\\n//   - be added together,\\n//   - be subtracted from each other,\\n//   - be multiplied by a scalar value (only uint256 in this implementation) - both on the left and on the right,\\n//   - the minimum be calculated among them,\\n//   - the maximum be calculated among them,\\n//   - the \\\"==\\\", \\\"!=\\\", \\\"<=\\\", \\\"<\\\", \\\">\\\", and \\\">=\\\" relations established between them, and\\n// The mulDiv() interactions will be taken care of later.\\n//\\n\\n// --- USDC ---------------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(UsdcQuantity left, UsdcQuantity right) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(UsdcQuantity.unwrap(left) + UsdcQuantity.unwrap(right));\\n}\\n\\nfunction sub(UsdcQuantity left, UsdcQuantity right) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(UsdcQuantity.unwrap(left) - UsdcQuantity.unwrap(right));\\n}\\n\\nfunction mul(UsdcQuantity val, uint256 x) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(UsdcQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, UsdcQuantity val) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(x * UsdcQuantity.unwrap(val));\\n}\\n\\nfunction min(UsdcQuantity left, UsdcQuantity right) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.min(UsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right)));\\n}\\n\\nfunction max(UsdcQuantity left, UsdcQuantity right) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.max(UsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right)));\\n}\\n\\nfunction eq(UsdcQuantity left, UsdcQuantity right) pure returns (bool) {\\n    return UsdcQuantity.unwrap(left) == UsdcQuantity.unwrap(right);\\n}\\n\\nfunction neq(UsdcQuantity left, UsdcQuantity right) pure returns (bool) {\\n    return UsdcQuantity.unwrap(left) != UsdcQuantity.unwrap(right);\\n}\\n\\nfunction lt(UsdcQuantity left, UsdcQuantity right) pure returns (bool) {\\n    return UsdcQuantity.unwrap(left) < UsdcQuantity.unwrap(right);\\n}\\n\\nfunction gt(UsdcQuantity left, UsdcQuantity right) pure returns (bool) {\\n    return UsdcQuantity.unwrap(left) > UsdcQuantity.unwrap(right);\\n}\\n\\nfunction lte(UsdcQuantity left, UsdcQuantity right) pure returns (bool) {\\n    return UsdcQuantity.unwrap(left) <= UsdcQuantity.unwrap(right);\\n}\\n\\nfunction gte(UsdcQuantity left, UsdcQuantity right) pure returns (bool) {\\n    return UsdcQuantity.unwrap(left) >= UsdcQuantity.unwrap(right);\\n}\\n\\n// --- MAI ----------------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(MaiQuantity left, MaiQuantity right) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(MaiQuantity.unwrap(left) + MaiQuantity.unwrap(right));\\n}\\n\\nfunction sub(MaiQuantity left, MaiQuantity right) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(MaiQuantity.unwrap(left) - MaiQuantity.unwrap(right));\\n}\\n\\nfunction mul(MaiQuantity val, uint256 x) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(MaiQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, MaiQuantity val) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(x * MaiQuantity.unwrap(val));\\n}\\n\\nfunction min(MaiQuantity left, MaiQuantity right) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.min(MaiQuantity.unwrap(left), MaiQuantity.unwrap(right)));\\n}\\n\\nfunction max(MaiQuantity left, MaiQuantity right) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.max(MaiQuantity.unwrap(left), MaiQuantity.unwrap(right)));\\n}\\n\\nfunction eq(MaiQuantity left, MaiQuantity right) pure returns (bool) {\\n    return MaiQuantity.unwrap(left) == MaiQuantity.unwrap(right);\\n}\\n\\nfunction neq(MaiQuantity left, MaiQuantity right) pure returns (bool) {\\n    return MaiQuantity.unwrap(left) != MaiQuantity.unwrap(right);\\n}\\n\\nfunction lt(MaiQuantity left, MaiQuantity right) pure returns (bool) {\\n    return MaiQuantity.unwrap(left) < MaiQuantity.unwrap(right);\\n}\\n\\nfunction gt(MaiQuantity left, MaiQuantity right) pure returns (bool) {\\n    return MaiQuantity.unwrap(left) > MaiQuantity.unwrap(right);\\n}\\n\\nfunction lte(MaiQuantity left, MaiQuantity right) pure returns (bool) {\\n    return MaiQuantity.unwrap(left) <= MaiQuantity.unwrap(right);\\n}\\n\\nfunction gte(MaiQuantity left, MaiQuantity right) pure returns (bool) {\\n    return MaiQuantity.unwrap(left) >= MaiQuantity.unwrap(right);\\n}\\n\\n// --- LP USDC/MAI --------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(LpQuantity left, LpQuantity right) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(LpQuantity.unwrap(left) + LpQuantity.unwrap(right));\\n}\\n\\nfunction sub(LpQuantity left, LpQuantity right) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(LpQuantity.unwrap(left) - LpQuantity.unwrap(right));\\n}\\n\\nfunction mul(LpQuantity val, uint256 x) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(LpQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, LpQuantity val) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(x * LpQuantity.unwrap(val));\\n}\\n\\nfunction min(LpQuantity left, LpQuantity right) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.min(LpQuantity.unwrap(left), LpQuantity.unwrap(right)));\\n}\\n\\nfunction max(LpQuantity left, LpQuantity right) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.max(LpQuantity.unwrap(left), LpQuantity.unwrap(right)));\\n}\\n\\nfunction eq(LpQuantity left, LpQuantity right) pure returns (bool) {\\n    return LpQuantity.unwrap(left) == LpQuantity.unwrap(right);\\n}\\n\\nfunction neq(LpQuantity left, LpQuantity right) pure returns (bool) {\\n    return LpQuantity.unwrap(left) != LpQuantity.unwrap(right);\\n}\\n\\nfunction lt(LpQuantity left, LpQuantity right) pure returns (bool) {\\n    return LpQuantity.unwrap(left) < LpQuantity.unwrap(right);\\n}\\n\\nfunction gt(LpQuantity left, LpQuantity right) pure returns (bool) {\\n    return LpQuantity.unwrap(left) > LpQuantity.unwrap(right);\\n}\\n\\nfunction lte(LpQuantity left, LpQuantity right) pure returns (bool) {\\n    return LpQuantity.unwrap(left) <= LpQuantity.unwrap(right);\\n}\\n\\nfunction gte(LpQuantity left, LpQuantity right) pure returns (bool) {\\n    return LpQuantity.unwrap(left) >= LpQuantity.unwrap(right);\\n}\\n\\n// --- PE -----------------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(PeQuantity left, PeQuantity right) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(PeQuantity.unwrap(left) + PeQuantity.unwrap(right));\\n}\\n\\nfunction sub(PeQuantity left, PeQuantity right) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(PeQuantity.unwrap(left) - PeQuantity.unwrap(right));\\n}\\n\\nfunction mul(PeQuantity val, uint256 x) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(PeQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, PeQuantity val) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(x * PeQuantity.unwrap(val));\\n}\\n\\nfunction min(PeQuantity left, PeQuantity right) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.min(PeQuantity.unwrap(left), PeQuantity.unwrap(right)));\\n}\\n\\nfunction max(PeQuantity left, PeQuantity right) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.max(PeQuantity.unwrap(left), PeQuantity.unwrap(right)));\\n}\\n\\nfunction eq(PeQuantity left, PeQuantity right) pure returns (bool) {\\n    return PeQuantity.unwrap(left) == PeQuantity.unwrap(right);\\n}\\n\\nfunction neq(PeQuantity left, PeQuantity right) pure returns (bool) {\\n    return PeQuantity.unwrap(left) != PeQuantity.unwrap(right);\\n}\\n\\nfunction lt(PeQuantity left, PeQuantity right) pure returns (bool) {\\n    return PeQuantity.unwrap(left) < PeQuantity.unwrap(right);\\n}\\n\\nfunction gt(PeQuantity left, PeQuantity right) pure returns (bool) {\\n    return PeQuantity.unwrap(left) > PeQuantity.unwrap(right);\\n}\\n\\nfunction lte(PeQuantity left, PeQuantity right) pure returns (bool) {\\n    return PeQuantity.unwrap(left) <= PeQuantity.unwrap(right);\\n}\\n\\nfunction gte(PeQuantity left, PeQuantity right) pure returns (bool) {\\n    return PeQuantity.unwrap(left) >= PeQuantity.unwrap(right);\\n}\\n\\n// --- QI -----------------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(QiQuantity left, QiQuantity right) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(QiQuantity.unwrap(left) + QiQuantity.unwrap(right));\\n}\\n\\nfunction sub(QiQuantity left, QiQuantity right) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(QiQuantity.unwrap(left) - QiQuantity.unwrap(right));\\n}\\n\\nfunction mul(QiQuantity val, uint256 x) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(QiQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, QiQuantity val) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(x * QiQuantity.unwrap(val));\\n}\\n\\nfunction min(QiQuantity left, QiQuantity right) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.min(QiQuantity.unwrap(left), QiQuantity.unwrap(right)));\\n}\\n\\nfunction max(QiQuantity left, QiQuantity right) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.max(QiQuantity.unwrap(left), QiQuantity.unwrap(right)));\\n}\\n\\nfunction eq(QiQuantity left, QiQuantity right) pure returns (bool) {\\n    return QiQuantity.unwrap(left) == QiQuantity.unwrap(right);\\n}\\n\\nfunction neq(QiQuantity left, QiQuantity right) pure returns (bool) {\\n    return QiQuantity.unwrap(left) != QiQuantity.unwrap(right);\\n}\\n\\nfunction lt(QiQuantity left, QiQuantity right) pure returns (bool) {\\n    return QiQuantity.unwrap(left) < QiQuantity.unwrap(right);\\n}\\n\\nfunction gt(QiQuantity left, QiQuantity right) pure returns (bool) {\\n    return QiQuantity.unwrap(left) > QiQuantity.unwrap(right);\\n}\\n\\nfunction lte(QiQuantity left, QiQuantity right) pure returns (bool) {\\n    return QiQuantity.unwrap(left) <= QiQuantity.unwrap(right);\\n}\\n\\nfunction gte(QiQuantity left, QiQuantity right) pure returns (bool) {\\n    return QiQuantity.unwrap(left) >= QiQuantity.unwrap(right);\\n}\\n\\n// --- PE/USDC ------------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(PePerUsdcQuantity.unwrap(left) + PePerUsdcQuantity.unwrap(right));\\n}\\n\\nfunction sub(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(PePerUsdcQuantity.unwrap(left) - PePerUsdcQuantity.unwrap(right));\\n}\\n\\nfunction mul(PePerUsdcQuantity val, uint256 x) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(PePerUsdcQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, PePerUsdcQuantity val) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(x * PePerUsdcQuantity.unwrap(val));\\n}\\n\\nfunction min(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.min(PePerUsdcQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right)));\\n}\\n\\nfunction max(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.max(PePerUsdcQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right)));\\n}\\n\\nfunction eq(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (bool) {\\n    return PePerUsdcQuantity.unwrap(left) == PePerUsdcQuantity.unwrap(right);\\n}\\n\\nfunction neq(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (bool) {\\n    return PePerUsdcQuantity.unwrap(left) != PePerUsdcQuantity.unwrap(right);\\n}\\n\\nfunction lt(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (bool) {\\n    return PePerUsdcQuantity.unwrap(left) < PePerUsdcQuantity.unwrap(right);\\n}\\n\\nfunction gt(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (bool) {\\n    return PePerUsdcQuantity.unwrap(left) > PePerUsdcQuantity.unwrap(right);\\n}\\n\\nfunction lte(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (bool) {\\n    return PePerUsdcQuantity.unwrap(left) <= PePerUsdcQuantity.unwrap(right);\\n}\\n\\nfunction gte(PePerUsdcQuantity left, PePerUsdcQuantity right) pure returns (bool) {\\n    return PePerUsdcQuantity.unwrap(left) >= PePerUsdcQuantity.unwrap(right);\\n}\\n\\n// --- USDC/PE ------------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(UsdcPerPeQuantity.unwrap(left) + UsdcPerPeQuantity.unwrap(right));\\n}\\n\\nfunction sub(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(UsdcPerPeQuantity.unwrap(left) - UsdcPerPeQuantity.unwrap(right));\\n}\\n\\nfunction mul(UsdcPerPeQuantity val, uint256 x) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(UsdcPerPeQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, UsdcPerPeQuantity val) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(x * UsdcPerPeQuantity.unwrap(val));\\n}\\n\\nfunction min(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.min(UsdcPerPeQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right)));\\n}\\n\\nfunction max(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.max(UsdcPerPeQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right)));\\n}\\n\\nfunction eq(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (bool) {\\n    return UsdcPerPeQuantity.unwrap(left) == UsdcPerPeQuantity.unwrap(right);\\n}\\n\\nfunction neq(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (bool) {\\n    return UsdcPerPeQuantity.unwrap(left) != UsdcPerPeQuantity.unwrap(right);\\n}\\n\\nfunction lt(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (bool) {\\n    return UsdcPerPeQuantity.unwrap(left) < UsdcPerPeQuantity.unwrap(right);\\n}\\n\\nfunction gt(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (bool) {\\n    return UsdcPerPeQuantity.unwrap(left) > UsdcPerPeQuantity.unwrap(right);\\n}\\n\\nfunction lte(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (bool) {\\n    return UsdcPerPeQuantity.unwrap(left) <= UsdcPerPeQuantity.unwrap(right);\\n}\\n\\nfunction gte(UsdcPerPeQuantity left, UsdcPerPeQuantity right) pure returns (bool) {\\n    return UsdcPerPeQuantity.unwrap(left) >= UsdcPerPeQuantity.unwrap(right);\\n}\\n\\n// --- 6-decimals ratio ---------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(RatioWith6Decimals.unwrap(left) + RatioWith6Decimals.unwrap(right));\\n}\\n\\nfunction sub(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(RatioWith6Decimals.unwrap(left) - RatioWith6Decimals.unwrap(right));\\n}\\n\\nfunction mul(RatioWith6Decimals val, uint256 x) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(RatioWith6Decimals.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, RatioWith6Decimals val) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(x * RatioWith6Decimals.unwrap(val));\\n}\\n\\nfunction min(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.min(RatioWith6Decimals.unwrap(left), RatioWith6Decimals.unwrap(right)));\\n}\\n\\nfunction max(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.max(RatioWith6Decimals.unwrap(left), RatioWith6Decimals.unwrap(right)));\\n}\\n\\nfunction eq(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (bool) {\\n    return RatioWith6Decimals.unwrap(left) == RatioWith6Decimals.unwrap(right);\\n}\\n\\nfunction neq(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (bool) {\\n    return RatioWith6Decimals.unwrap(left) != RatioWith6Decimals.unwrap(right);\\n}\\n\\nfunction lt(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (bool) {\\n    return RatioWith6Decimals.unwrap(left) < RatioWith6Decimals.unwrap(right);\\n}\\n\\nfunction gt(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (bool) {\\n    return RatioWith6Decimals.unwrap(left) > RatioWith6Decimals.unwrap(right);\\n}\\n\\nfunction lte(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (bool) {\\n    return RatioWith6Decimals.unwrap(left) <= RatioWith6Decimals.unwrap(right);\\n}\\n\\nfunction gte(RatioWith6Decimals left, RatioWith6Decimals right) pure returns (bool) {\\n    return RatioWith6Decimals.unwrap(left) >= RatioWith6Decimals.unwrap(right);\\n}\\n\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n// --- MulDiv Interactions ------------------------------------------------------------------------------------------------------------------------------------\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    MaiQuantity right,\\n    LpQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), MaiQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    PePerUsdcQuantity right,\\n    LpQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    PeQuantity right,\\n    LpQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), PeQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    QiQuantity right,\\n    LpQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), QiQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    RatioWith6Decimals right,\\n    LpQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(LpQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UsdcPerPeQuantity right,\\n    LpQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UsdcQuantity right,\\n    LpQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UsdcQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    uint256 right,\\n    LpQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(LpQuantity.unwrap(left), right, LpQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    LpQuantity right,\\n    MaiQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), LpQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    PePerUsdcQuantity right,\\n    MaiQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    PeQuantity right,\\n    MaiQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), PeQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    QiQuantity right,\\n    MaiQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), QiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    RatioWith6Decimals right,\\n    MaiQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(MaiQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcPerPeQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    uint256 right,\\n    MaiQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(MaiQuantity.unwrap(left), right, MaiQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    LpQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), LpQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    MaiQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), MaiQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    PeQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), PeQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    QiQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), QiQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    RatioWith6Decimals right,\\n    PePerUsdcQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcPerPeQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcPerPeQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcQuantity right,\\n    PeQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    uint256 right,\\n    PePerUsdcQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(PePerUsdcQuantity.unwrap(left), right, PePerUsdcQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    LpQuantity right,\\n    PeQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), LpQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    MaiQuantity right,\\n    PeQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), MaiQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    PePerUsdcQuantity right,\\n    PeQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    QiQuantity right,\\n    PeQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), QiQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    RatioWith6Decimals right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    RatioWith6Decimals right,\\n    PeQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(PeQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    RatioWith6Decimals right,\\n    UsdcQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UsdcPerPeQuantity right,\\n    PeQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UsdcPerPeQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(PeQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UsdcQuantity right,\\n    PeQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UsdcQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    uint256 right,\\n    PeQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(PeQuantity.unwrap(left), right, PeQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    LpQuantity right,\\n    QiQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), LpQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    MaiQuantity right,\\n    QiQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), MaiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    PePerUsdcQuantity right,\\n    QiQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    PeQuantity right,\\n    QiQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), PeQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    RatioWith6Decimals right,\\n    QiQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(QiQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UsdcPerPeQuantity right,\\n    QiQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UsdcQuantity right,\\n    QiQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UsdcQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    uint256 right,\\n    QiQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(QiQuantity.unwrap(left), right, QiQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    LpQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), LpQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    MaiQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), MaiQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    PePerUsdcQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), PePerUsdcQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    PeQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), PeQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    PeQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), PeQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    PeQuantity right,\\n    UsdcQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), PeQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    QiQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), QiQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    RatioWith6Decimals right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), RatioWith6Decimals.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    RatioWith6Decimals right,\\n    UsdcPerPeQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), RatioWith6Decimals.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UsdcPerPeQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UsdcPerPeQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UsdcQuantity right,\\n    PeQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UsdcQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UsdcQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UsdcQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UsdcQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UsdcQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    uint256 right,\\n    RatioWith6Decimals div\\n) pure returns (uint256) {\\n    return Math.mulDiv(RatioWith6Decimals.unwrap(left), right, RatioWith6Decimals.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    LpQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), LpQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    MaiQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), MaiQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    PePerUsdcQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    PePerUsdcQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    PeQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), PeQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    PeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), PeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    PeQuantity right,\\n    UsdcQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), PeQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    QiQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), QiQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    RatioWith6Decimals right,\\n    UsdcPerPeQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UsdcQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    uint256 right,\\n    UsdcPerPeQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(UsdcPerPeQuantity.unwrap(left), right, UsdcPerPeQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    LpQuantity right,\\n    UsdcQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), LpQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    MaiQuantity right,\\n    UsdcQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), MaiQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    PePerUsdcQuantity right,\\n    PeQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    PePerUsdcQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    PePerUsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    PeQuantity right,\\n    UsdcQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), PeQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    QiQuantity right,\\n    UsdcQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), QiQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    RatioWith6Decimals right,\\n    PeQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    RatioWith6Decimals right,\\n    UsdcPerPeQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    RatioWith6Decimals right,\\n    UsdcQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    uint256 right,\\n    UsdcQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(UsdcQuantity.unwrap(left), right, UsdcQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, LpQuantity.unwrap(right), LpQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    LpQuantity right,\\n    uint256 div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(left, LpQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, MaiQuantity.unwrap(right), MaiQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    MaiQuantity right,\\n    uint256 div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(left, MaiQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    PePerUsdcQuantity right,\\n    uint256 div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(left, PePerUsdcQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, PeQuantity.unwrap(right), PeQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    PeQuantity right,\\n    uint256 div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(left, PeQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, QiQuantity.unwrap(right), QiQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    QiQuantity right,\\n    uint256 div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(left, QiQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    RatioWith6Decimals right,\\n    uint256 div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(left, RatioWith6Decimals.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UsdcPerPeQuantity right,\\n    uint256 div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(left, UsdcPerPeQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UsdcQuantity right,\\n    uint256 div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(left, UsdcQuantity.unwrap(right), div));\\n}\\n\",\"keccak256\":\"0x594ba679a0276fcc86197ed0eb2fcfd754933a73fe009aabb901219ecd0f827a\",\"license\":\"MIT\"},\"contracts/Peronio.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n// OpenZeppelin imports\\nimport {AccessControl} from \\\"@openzeppelin/contracts_latest/access/AccessControl.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts_latest/security/ReentrancyGuard.sol\\\";\\nimport {ERC20} from \\\"@openzeppelin/contracts_latest/token/ERC20/ERC20.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts_latest/token/ERC20/IERC20.sol\\\";\\nimport {ERC20Permit} from \\\"@openzeppelin/contracts_latest/token/ERC20/extensions/draft-ERC20Permit.sol\\\";\\nimport {ERC20Burnable} from \\\"@openzeppelin/contracts_latest/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts_latest/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\n// QiDao\\nimport {IFarm} from \\\"./qidao/IFarm.sol\\\";\\n\\n// UniSwap\\nimport {IERC20Uniswap} from \\\"./uniswap/interfaces/IERC20Uniswap.sol\\\";\\nimport {IUniswapV2Pair} from \\\"./uniswap/interfaces/IUniswapV2Pair.sol\\\";\\nimport {IUniswapV2Router02} from \\\"./uniswap/interfaces/IUniswapV2Router02.sol\\\";\\n\\n// Interface & support\\nimport \\\"./PeronioSupport.sol\\\";\\n\\nstring constant NAME = \\\"Peronio\\\";\\nstring constant SYMBOL = \\\"P\\\";\\n\\ncontract Peronio is IPeronio, ERC20, ERC20Burnable, ERC20Permit, ERC165, AccessControl, ReentrancyGuard {\\n    using SafeERC20 for IERC20;\\n\\n    // Roles\\n    RoleId public constant override MARKUP_ROLE = RoleId.wrap(keccak256(\\\"MARKUP_ROLE\\\"));\\n    RoleId public constant override REWARDS_ROLE = RoleId.wrap(keccak256(\\\"REWARDS_ROLE\\\"));\\n    RoleId public constant override MIGRATOR_ROLE = RoleId.wrap(keccak256(\\\"MIGRATOR_ROLE\\\"));\\n\\n    // USDC Token Address\\n    address public immutable override usdcAddress;\\n    // MAI Token Address\\n    address public immutable override maiAddress;\\n    // LP USDC/MAI Address from QuickSwap\\n    address public immutable override lpAddress;\\n    // QI Token Address\\n    address public immutable override qiAddress;\\n\\n    // QuickSwap Router Address\\n    address public immutable override quickSwapRouterAddress;\\n\\n    // QiDao Farm Address\\n    address public immutable override qiDaoFarmAddress;\\n    // QiDao Pool ID\\n    uint256 public immutable override qiDaoPoolId;\\n\\n    // Constant number of significant decimals\\n    uint8 private constant DECIMALS = 6;\\n\\n    // One-hour constant\\n    uint256 private constant ONE_HOUR = 60 * 60; /* 60 minutes * 60 seconds */\\n\\n    // Rational constant one\\n    RatioWith6Decimals private constant ONE = RatioWith6Decimals.wrap(10**DECIMALS);\\n\\n    // Fees\\n    RatioWith6Decimals public override markupFee = RatioWith6Decimals.wrap(50000); // 5.00%\\n    RatioWith6Decimals public override swapFee = RatioWith6Decimals.wrap(1500); // 0.15%\\n\\n    // Initialization can only be run once\\n    bool public override initialized;\\n\\n    /**\\n     * Allow execution by the default admin only\\n     *\\n     */\\n    modifier onlyAdminRole() {\\n        _checkRole(DEFAULT_ADMIN_ROLE);\\n        _;\\n    }\\n\\n    /**\\n     * Allow execution by the markup-setter only\\n     *\\n     */\\n    modifier onlyMarkupRole() {\\n        _checkRole(RoleId.unwrap(MARKUP_ROLE));\\n        _;\\n    }\\n\\n    /**\\n     * Allow execution by the rewards-reaper only\\n     *\\n     */\\n    modifier onlyRewardsRole() {\\n        _checkRole(RoleId.unwrap(REWARDS_ROLE));\\n        _;\\n    }\\n\\n    /**\\n     * Allow execution by the migrator only\\n     *\\n     */\\n    modifier onlyMigratorRole() {\\n        _checkRole(RoleId.unwrap(MIGRATOR_ROLE));\\n        _;\\n    }\\n\\n    // --------------------------------------------------------------------------------------------------------------------------------------------------------\\n    // --- Public Interface -----------------------------------------------------------------------------------------------------------------------------------\\n    // --------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Construct a new Peronio contract\\n     *\\n     * @param _usdcAddress  Address used for the USDC tokens in vault\\n     * @param _maiAddress  Address used for the MAI tokens in vault\\n     * @param _lpAddress  LP Address for MAI/USDC\\n     * @param _qiAddress  Address used for the QI tokens in vault\\n     * @param _quickSwapRouterAddress  Address of the QuickSwap Router to talk to\\n     * @param _qiDaoFarmAddress  Address of the QiDao Farm to use\\n     * @param _qiDaoPoolId  Pool ID within the QiDao Farm\\n     */\\n    constructor(\\n        address _usdcAddress,\\n        address _maiAddress,\\n        address _lpAddress,\\n        address _qiAddress,\\n        address _quickSwapRouterAddress,\\n        address _qiDaoFarmAddress,\\n        uint256 _qiDaoPoolId\\n    ) ERC20(NAME, SYMBOL) ERC20Permit(NAME) {\\n        // --- Gas Saving -------------------------------------------------------------------------\\n        address sender = _msgSender();\\n\\n        // Stablecoin Addresses\\n        usdcAddress = _usdcAddress;\\n        maiAddress = _maiAddress;\\n\\n        // LP USDC/MAI Address\\n        lpAddress = _lpAddress;\\n\\n        // Router Address\\n        quickSwapRouterAddress = _quickSwapRouterAddress;\\n\\n        // QiDao Data\\n        qiDaoFarmAddress = _qiDaoFarmAddress;\\n        qiDaoPoolId = _qiDaoPoolId;\\n        qiAddress = _qiAddress;\\n\\n        // Grant roles\\n        _setupRole(DEFAULT_ADMIN_ROLE, sender);\\n        _setupRole(RoleId.unwrap(MARKUP_ROLE), sender);\\n        _setupRole(RoleId.unwrap(REWARDS_ROLE), sender);\\n        _setupRole(RoleId.unwrap(MIGRATOR_ROLE), sender);\\n    }\\n\\n    /**\\n     * Implementation of the IERC165 interface\\n     *\\n     * @param interfaceId  Interface ID to check against\\n     * @return  Whether the provided interface ID is supported\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, ERC165) returns (bool) {\\n        return interfaceId == type(IPeronio).interfaceId || super.supportsInterface(interfaceId);\\n    }\\n\\n    // --- Decimals -------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the number of decimals the PE token will work with\\n     *\\n     * @return decimals_  This will always be 6\\n     */\\n    function decimals() public view virtual override(ERC20, IPeronio) returns (uint8 decimals_) {\\n        decimals_ = DECIMALS;\\n    }\\n\\n    // --- Markup fee change ----------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Set the markup fee to the given value (take into account that this will use `DECIMALS` decimals implicitly)\\n     *\\n     * @param newMarkupFee  New markup fee value\\n     * @return prevMarkupFee  Previous markup fee value\\n     * @custom:emit  MarkupFeeUpdated\\n     */\\n    function setMarkupFee(RatioWith6Decimals newMarkupFee) external override onlyMarkupRole returns (RatioWith6Decimals prevMarkupFee) {\\n        (prevMarkupFee, markupFee) = (markupFee, newMarkupFee);\\n\\n        emit MarkupFeeUpdated(_msgSender(), newMarkupFee);\\n    }\\n\\n    // --- Initialization -------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Initialize the PE token by providing collateral USDC tokens - initial conversion rate will be set at the given starting ratio\\n     *\\n     * @param usdcAmount  Number of collateral USDC tokens\\n     * @param startingRatio  Initial minting ratio in PE tokens per USDC tokens minted (including DECIMALS)\\n     * @custom:emit  Initialized\\n     */\\n    function initialize(UsdcQuantity usdcAmount, PePerUsdcQuantity startingRatio) external override onlyAdminRole {\\n        // Prevent double initialization\\n        require(!initialized, \\\"Contract already initialized\\\");\\n        initialized = true;\\n\\n        // --- Gas Saving -------------------------------------------------------------------------\\n        IERC20 maiERC20 = IERC20(maiAddress);\\n        IERC20 usdcERC20 = IERC20(usdcAddress);\\n        IERC20 lpERC20 = IERC20(lpAddress);\\n        IERC20 qiERC20 = IERC20(qiAddress);\\n        address sender = _msgSender();\\n        address _quickSwapRouterAddress = quickSwapRouterAddress;\\n        uint256 maxVal = type(uint256).max;\\n\\n        // Transfer initial USDC amount from user to current contract\\n        usdcERC20.safeTransferFrom(sender, address(this), UsdcQuantity.unwrap(usdcAmount));\\n\\n        // Unlimited ERC20 approval for Router\\n        maiERC20.approve(_quickSwapRouterAddress, maxVal);\\n        usdcERC20.approve(_quickSwapRouterAddress, maxVal);\\n        lpERC20.approve(_quickSwapRouterAddress, maxVal);\\n        qiERC20.approve(_quickSwapRouterAddress, maxVal);\\n\\n        // Commit the complete initial USDC amount\\n        _zapIn(usdcAmount);\\n        usdcAmount = _stakedValue();\\n\\n        // Mints exactly startingRatio for each collateral USDC token\\n        _mint(sender, PeQuantity.unwrap(mulDiv(usdcAmount, startingRatio, ONE)));\\n\\n        emit Initialized(sender, usdcAmount, startingRatio);\\n    }\\n\\n    // --- State views ----------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the USDC and MAI token reserves present in QuickSwap\\n     *\\n     * @return usdcReserves  Number of USDC tokens in reserve\\n     * @return maiReserves  Number of MAI tokens in reserve\\n     */\\n    function getLpReserves() external view override returns (UsdcQuantity usdcReserves, MaiQuantity maiReserves) {\\n        (usdcReserves, maiReserves) = _getLpReserves();\\n    }\\n\\n    /**\\n     * Return the number of LP USDC/MAI tokens on stake at QiDao's Farm\\n     *\\n     * @return lpAmount  Number of LP USDC/MAI token on stake\\n     */\\n    function stakedBalance() external view override returns (LpQuantity lpAmount) {\\n        lpAmount = _stakedBalance();\\n    }\\n\\n    /**\\n     * Return the number of USDC and MAI tokens on stake at QiDao's Farm\\n     *\\n     * @return usdcAmount  Number of USDC tokens on stake\\n     * @return maiAmount  Number of MAI tokens on stake\\n     */\\n    function stakedTokens() external view override returns (UsdcQuantity usdcAmount, MaiQuantity maiAmount) {\\n        (usdcAmount, maiAmount) = _stakedTokens();\\n    }\\n\\n    /**\\n     * Return the equivalent number of USDC tokens on stake at QiDao's Farm\\n     *\\n     * @return usdcAmount  Total equivalent number of USDC token on stake\\n     */\\n    function stakedValue() external view override returns (UsdcQuantity usdcAmount) {\\n        usdcAmount = _stakedValue();\\n    }\\n\\n    /**\\n     * Return the _collateralized_ price in USDC tokens per PE token\\n     *\\n     * @return price  Collateralized price in USDC tokens per PE token\\n     */\\n    function usdcPrice() external view override returns (PePerUsdcQuantity price) {\\n        price = mulDiv(ONE, _totalSupply(), _stakedValue());\\n    }\\n\\n    /**\\n     * Return the effective _minting_ price in USDC tokens per PE token\\n     *\\n     * @return price  Minting price in USDC tokens per PE token\\n     */\\n    function buyingPrice() external view override returns (UsdcPerPeQuantity price) {\\n        price = mulDiv(_collateralRatio(), add(ONE, markupFee), ONE);\\n    }\\n\\n    /**\\n     * Return the ratio of total number of USDC tokens per PE token\\n     *\\n     * @return ratio  Ratio of USDC tokens per PE token, with `_decimal` decimals\\n     */\\n    function collateralRatio() external view override returns (UsdcPerPeQuantity ratio) {\\n        ratio = _collateralRatio();\\n    }\\n\\n    // --- State changers -------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Mint PE tokens using the provided USDC tokens as collateral\\n     *\\n     * @param to  The address to transfer the minted PE tokens to\\n     * @param usdcAmount  Number of USDC tokens to use as collateral\\n     * @param minReceive  The minimum number of PE tokens to mint\\n     * @return peAmount  The number of PE tokens actually minted\\n     * @custom:emit  Minted\\n     */\\n    function mint(\\n        address to,\\n        UsdcQuantity usdcAmount,\\n        PeQuantity minReceive\\n    ) external override nonReentrant returns (PeQuantity peAmount) {\\n        peAmount = _mintPe(to, usdcAmount, minReceive, markupFee);\\n    }\\n\\n    /**\\n     * Mint PE tokens using the provided USDC tokens as collateral --- used by the migrators in order not to incur normal fees\\n     *\\n     * @param to  The address to transfer the minted PE tokens to\\n     * @param usdcAmount  Number of USDC tokens to use as collateral\\n     * @param minReceive  The minimum number of PE tokens to mint\\n     * @return peAmount  The number of PE tokens actually minted\\n     * @custom:emit  Minted\\n     */\\n    function mintForMigration(\\n        address to,\\n        UsdcQuantity usdcAmount,\\n        PeQuantity minReceive\\n    ) external override nonReentrant onlyMigratorRole returns (PeQuantity peAmount) {\\n        peAmount = _mintPe(to, usdcAmount, minReceive, RatioWith6Decimals.wrap(0));\\n    }\\n\\n    /**\\n     * Extract the given number of PE tokens as USDC tokens\\n     *\\n     * @param to  Address to deposit extracted USDC tokens into\\n     * @param peAmount  Number of PE tokens to withdraw\\n     * @return usdcTotal  Number of USDC tokens extracted\\n     * @custom:emit  Withdrawal\\n     */\\n    function withdraw(address to, PeQuantity peAmount) external override nonReentrant returns (UsdcQuantity usdcTotal) {\\n        // --- Gas Saving -------------------------------------------------------------------------\\n        address sender = _msgSender();\\n\\n        // Calculate equivalent number of LP USDC/MAI tokens for the given burnt PE tokens\\n        LpQuantity lpAmount = mulDiv(peAmount, _stakedBalance(), _totalSupply());\\n\\n        // Extract the given number of LP USDC/MAI tokens as USDC tokens\\n        usdcTotal = _zapOut(lpAmount);\\n\\n        // Transfer USDC tokens the the given address\\n        IERC20(usdcAddress).safeTransfer(to, UsdcQuantity.unwrap(usdcTotal));\\n\\n        // Burn the given number of PE tokens\\n        _burn(sender, PeQuantity.unwrap(peAmount));\\n\\n        emit Withdrawal(sender, usdcTotal, peAmount);\\n    }\\n\\n    /**\\n     * Extract the given number of PE tokens as LP USDC/MAI tokens\\n     *\\n     * @param to  Address to deposit extracted LP USDC/MAI tokens into\\n     * @param peAmount  Number of PE tokens to withdraw liquidity for\\n     * @return lpAmount  Number of LP USDC/MAI tokens extracted\\n     * @custom:emit LiquidityWithdrawal\\n     */\\n    function withdrawLiquidity(address to, PeQuantity peAmount) external override nonReentrant returns (LpQuantity lpAmount) {\\n        // --- Gas Saving -------------------------------------------------------------------------\\n        address sender = _msgSender();\\n\\n        // Calculate equivalent number of LP USDC/MAI tokens for the given burnt PE tokens\\n        lpAmount = mulDiv(peAmount, _stakedBalance(), _totalSupply());\\n\\n        // Get LP USDC/MAI tokens out of QiDao's Farm\\n        _unstakeLP(lpAmount);\\n\\n        // Transfer LP USDC/MAI tokens to the given address\\n        IERC20(lpAddress).safeTransfer(to, LpQuantity.unwrap(lpAmount));\\n\\n        // Burn the given number of PE tokens\\n        _burn(sender, PeQuantity.unwrap(peAmount));\\n\\n        emit LiquidityWithdrawal(sender, lpAmount, peAmount);\\n    }\\n\\n    // --- Rewards --------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the rewards accrued by staking LP USDC/MAI tokens in QiDao's Farm (in QI tokens)\\n     *\\n     * @return qiAmount  Number of QI tokens accrued\\n     */\\n    function getPendingRewardsAmount() external view override returns (QiQuantity qiAmount) {\\n        qiAmount = _getPendingRewardsAmount();\\n    }\\n\\n    /**\\n     * Claim QiDao's QI token rewards, and re-invest them in the QuickSwap liquidity pool and QiDao's Farm\\n     *\\n     * @return usdcAmount  The number of USDC tokens being re-invested\\n     * @return lpAmount  The number of LP USDC/MAI tokens being put on stake\\n     * @custom:emit CompoundRewards\\n     */\\n    function compoundRewards() external override onlyRewardsRole returns (UsdcQuantity usdcAmount, LpQuantity lpAmount) {\\n        // Claim rewards from QiDao's Farm\\n        IFarm(qiDaoFarmAddress).deposit(qiDaoPoolId, 0);\\n\\n        // Retrieve the number of QI tokens rewarded and swap them to USDC tokens\\n        QiQuantity amount = QiQuantity.wrap(IERC20(qiAddress).balanceOf(address(this)));\\n        _swapTokens(amount);\\n\\n        // Commit all USDC tokens so converted to the QuickSwap liquidity pool\\n        usdcAmount = UsdcQuantity.wrap(IERC20(usdcAddress).balanceOf(address(this)));\\n        lpAmount = _zapIn(usdcAmount);\\n\\n        emit CompoundRewards(amount, usdcAmount, lpAmount);\\n    }\\n\\n    // --- Quotes ---------------------------------------------------------------------------------------------------------------------------------------------\\n    //\\n    // Quotes are created by inlining the calls to mint (for quoteIn) and withdraw (for quoteOut), and discarding state-changing statements\\n    //\\n\\n    /**\\n     * Retrieve the expected number of PE tokens corresponding to the given number of USDC tokens for minting.\\n     *\\n     * @dev This method was obtained by _inlining_ the call to mint() across contracts, and cleaning up the result.\\n     *\\n     * @param usdc  Number of USDC tokens to quote for\\n     * @return pe  Number of PE tokens quoted for the given number of USDC tokens\\n     */\\n    function quoteIn(UsdcQuantity usdc) external view override returns (PeQuantity pe) {\\n        // --- Gas Saving -------------------------------------------------------------------------\\n        address _lpAddress = lpAddress;\\n\\n        // retrieve LP state (simulations will modify these)\\n        (UsdcQuantity usdcReserves, MaiQuantity maiReserves) = _getLpReserves();\\n        LpQuantity lpTotalSupply = LpQuantity.wrap(IERC20(_lpAddress).totalSupply());\\n\\n        // -- SPLIT -------------------------------------------------------------------------------\\n        UsdcQuantity usdcAmount = _calculateSwapInAmount(usdcReserves, usdc);\\n        MaiQuantity maiAmount = _getAmountOut(usdcAmount, usdcReserves, maiReserves);\\n\\n        // simulate LP state update\\n        usdcReserves = add(usdcReserves, usdcAmount);\\n        maiReserves = sub(maiReserves, maiAmount);\\n\\n        // -- SWAP --------------------------------------------------------------------------------\\n\\n        // calculate actual values swapped\\n        {\\n            MaiQuantity amountMaiOptimal = mulDiv(sub(usdc, usdcAmount), maiReserves, usdcReserves);\\n            if (lte(amountMaiOptimal, maiAmount)) {\\n                (usdcAmount, maiAmount) = (sub(usdc, usdcAmount), amountMaiOptimal);\\n            } else {\\n                UsdcQuantity amountUsdcOptimal = mulDiv(maiAmount, usdcReserves, maiReserves);\\n                (usdcAmount, maiAmount) = (amountUsdcOptimal, maiAmount);\\n            }\\n        }\\n\\n        // deal with LP minting when changing its K\\n        {\\n            UniSwapRootKQuantity rootK = sqrt(mul(usdcReserves, maiReserves));\\n            UniSwapRootKQuantity rootKLast = sqrt(UniSwapKQuantity.wrap(IUniswapV2Pair(_lpAddress).kLast()));\\n            if (lt(rootKLast, rootK)) {\\n                lpTotalSupply = add(lpTotalSupply, mulDiv(lpTotalSupply, sub(rootK, rootKLast), add(mul(rootK, 5), rootKLast)));\\n            }\\n        }\\n\\n        // calculate LP values actually provided\\n        LpQuantity zapInLps;\\n        {\\n            LpQuantity maiCandidate = mulDiv(maiAmount, lpTotalSupply, maiReserves);\\n            LpQuantity usdcCandidate = mulDiv(usdcAmount, lpTotalSupply, usdcReserves);\\n            zapInLps = min(maiCandidate, usdcCandidate);\\n        }\\n\\n        // -- PERONIO -----------------------------------------------------------------------------\\n        LpQuantity lpAmount = mulDiv(zapInLps, sub(ONE, _totalMintFee(markupFee)), ONE);\\n        pe = mulDiv(lpAmount, _totalSupply(), _stakedBalance());\\n    }\\n\\n    /**\\n     * Retrieve the expected number of USDC tokens corresponding to the given number of PE tokens for withdrawal.\\n     *\\n     * @dev This method was obtained by _inlining_ the call to withdraw() across contracts, and cleaning up the result.\\n     *\\n     * @param pe  Number of PE tokens to quote for\\n     * @return usdc  Number of USDC tokens quoted for the given number of PE tokens\\n     */\\n    function quoteOut(PeQuantity pe) external view override returns (UsdcQuantity usdc) {\\n        // --- Gas Saving -------------------------------------------------------------------------\\n        address _lpAddress = lpAddress;\\n\\n        (UsdcQuantity usdcReserves, MaiQuantity maiReserves) = _getLpReserves();\\n        LpQuantity lpTotalSupply = LpQuantity.wrap(IERC20(_lpAddress).totalSupply());\\n\\n        // deal with LP minting when changing its K\\n        {\\n            UniSwapRootKQuantity rootK = sqrt(mul(usdcReserves, maiReserves));\\n            UniSwapRootKQuantity rootKLast = sqrt(UniSwapKQuantity.wrap(IUniswapV2Pair(_lpAddress).kLast()));\\n            if (lt(rootKLast, rootK)) {\\n                lpTotalSupply = add(lpTotalSupply, mulDiv(lpTotalSupply, sub(rootK, rootKLast), add(mul(rootK, 5), rootKLast)));\\n            }\\n        }\\n\\n        // calculate LP values actually withdrawn\\n        LpQuantity lpAmount = add(LpQuantity.wrap(IERC20Uniswap(_lpAddress).balanceOf(_lpAddress)), mulDiv(pe, _stakedBalance(), _totalSupply()));\\n\\n        UsdcQuantity usdcAmount = mulDiv(usdcReserves, lpAmount, lpTotalSupply);\\n        MaiQuantity maiAmount = mulDiv(maiReserves, lpAmount, lpTotalSupply);\\n\\n        usdc = add(usdcAmount, _getAmountOut(maiAmount, sub(maiReserves, maiAmount), sub(usdcReserves, usdcAmount)));\\n    }\\n\\n    // --------------------------------------------------------------------------------------------------------------------------------------------------------\\n    // --- Private Interface ----------------------------------------------------------------------------------------------------------------------------------\\n    // --------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    /**\\n     * Return the number of PE tokens in existence\\n     *\\n     * @return peAmount  Number of PE tokens in existence\\n     */\\n    function _totalSupply() internal view returns (PeQuantity peAmount) {\\n        peAmount = PeQuantity.wrap(totalSupply());\\n    }\\n\\n    /**\\n     * Return the USDC and MAI token reserves present in QuickSwap\\n     *\\n     * @return usdcReserves  Number of USDC tokens in reserve\\n     * @return maiReserves  Number of MAI tokens in reserve\\n     */\\n    function _getLpReserves() internal view returns (UsdcQuantity usdcReserves, MaiQuantity maiReserves) {\\n        (uint112 reserve0, uint112 reserve1, ) = IUniswapV2Pair(lpAddress).getReserves();\\n        (usdcReserves, maiReserves) = usdcAddress < maiAddress\\n            ? (UsdcQuantity.wrap(reserve0), MaiQuantity.wrap(reserve1))\\n            : (UsdcQuantity.wrap(reserve1), MaiQuantity.wrap(reserve0));\\n    }\\n\\n    /**\\n     * Return the number of LP USDC/MAI tokens on stake at QiDao's Farm\\n     *\\n     * @return lpAmount  Number of LP USDC/MAI token on stake\\n     */\\n    function _stakedBalance() internal view returns (LpQuantity lpAmount) {\\n        lpAmount = LpQuantity.wrap(IFarm(qiDaoFarmAddress).deposited(qiDaoPoolId, address(this)));\\n    }\\n\\n    /**\\n     * Return the number of USDC and MAI tokens on stake at QiDao's Farm\\n     *\\n     * @return usdcAmount  Number of USDC tokens on stake\\n     * @return maiAmount  Number of MAI tokens on stake\\n     */\\n    function _stakedTokens() internal view returns (UsdcQuantity usdcAmount, MaiQuantity maiAmount) {\\n        LpQuantity lpAmount = _stakedBalance();\\n        LpQuantity lpTotalSupply = LpQuantity.wrap(IERC20(lpAddress).totalSupply());\\n\\n        (UsdcQuantity usdcReserves, MaiQuantity maiReserves) = _getLpReserves();\\n\\n        usdcAmount = mulDiv(lpAmount, usdcReserves, lpTotalSupply);\\n        maiAmount = mulDiv(lpAmount, maiReserves, lpTotalSupply);\\n    }\\n\\n    /**\\n     * Return the equivalent number of USDC tokens on stake at QiDao's Farm\\n     *\\n     * This method will return the equivalent number of USDC tokens for the number of USDC and MAI tokens on stake.\\n     *\\n     * @return totalUSDC  Total equivalent number of USDC token on stake\\n     */\\n    function _stakedValue() internal view returns (UsdcQuantity totalUSDC) {\\n        (UsdcQuantity usdcReserves, MaiQuantity maiReserves) = _getLpReserves();\\n        (UsdcQuantity usdcAmount, MaiQuantity maiAmount) = _stakedTokens();\\n\\n        // Simulate Swap\\n        totalUSDC = add(usdcAmount, _getAmountOut(maiAmount, maiReserves, usdcReserves));\\n    }\\n\\n    /**\\n     * Return the ratio of total number of USDC tokens per PE token\\n     *\\n     * @return ratio  Ratio of USDC tokens per PE token, with `_decimal` decimals\\n     */\\n    function _collateralRatio() internal view returns (UsdcPerPeQuantity ratio) {\\n        ratio = mulDiv(ONE, _stakedValue(), _totalSupply());\\n    }\\n\\n    /**\\n     * Return the total minting fee to apply\\n     *\\n     * @return totalFee  The total fee to apply on minting\\n     */\\n    function _totalMintFee(RatioWith6Decimals _markupFee) internal view returns (RatioWith6Decimals totalFee) {\\n        // Retrieve the deposit fee from QiDao's Farm (this is always expressed with 4 decimals, as \\\"basic points\\\")\\n        // Convert these \\\"basic points\\\" to `DECIMALS` precision\\n        (, , , , uint16 depositFeeBP) = IFarm(qiDaoFarmAddress).poolInfo(qiDaoPoolId);\\n        RatioWith6Decimals depositFee = ratio4to6(RatioWith4Decimals.wrap(depositFeeBP));\\n\\n        // Calculate total fee to apply\\n        // (ie. the swapFee and the depositFee are included in the total markup fee, thus, we don't double charge for both the markup fee itself\\n        // and the swap and deposit fees)\\n        totalFee = max(_markupFee, add(swapFee, depositFee));\\n    }\\n\\n    /**\\n     * Actually mint PE tokens using the provided USDC tokens as collateral, applying the given markup fee\\n     *\\n     * @param to  The address to transfer the minted PE tokens to\\n     * @param usdcAmount  Number of USDC tokens to use as collateral\\n     * @param minReceive  The minimum number of PE tokens to mint\\n     * @param _markupFee  The markup fee to apply\\n     * @return peAmount  The number of PE tokens actually minted\\n     * @custom:emit  Minted\\n     */\\n    function _mintPe(\\n        address to,\\n        UsdcQuantity usdcAmount,\\n        PeQuantity minReceive,\\n        RatioWith6Decimals _markupFee\\n    ) internal returns (PeQuantity peAmount) {\\n        // --- Gas Saving -------------------------------------------------------------------------\\n        address sender = _msgSender();\\n\\n        // Transfer USDC tokens as collateral to this contract\\n        IERC20(usdcAddress).safeTransferFrom(sender, address(this), UsdcQuantity.unwrap(usdcAmount));\\n\\n        // Remember the previously staked balance\\n        LpQuantity stakedAmount = _stakedBalance();\\n\\n        // Commit USDC tokens, and discount fees totalling the markup fee\\n        LpQuantity lpAmount = mulDiv(_zapIn(usdcAmount), sub(ONE, _totalMintFee(_markupFee)), ONE);\\n\\n        // Calculate the number of PE tokens as the proportion of liquidity provided\\n        peAmount = mulDiv(lpAmount, _totalSupply(), stakedAmount);\\n\\n        require(lte(minReceive, peAmount), \\\"Minimum required not met\\\");\\n\\n        // Actually mint the PE tokens\\n        _mint(to, PeQuantity.unwrap(peAmount));\\n\\n        emit Minted(sender, usdcAmount, peAmount);\\n    }\\n\\n    /**\\n     * Commit the given number of USDC tokens\\n     *\\n     * This method will:\\n     *   1. split the given USDC amount into USDC/MAI amounts so as to provide balanced liquidity,\\n     *   2. add the given amounts of USDC and MAI tokens to the liquidity pool, and obtain LP USDC/MAI tokens in return, and\\n     *   3. stake the given LP USDC/MAI tokens in QiDao's Farm so as to accrue rewards therein.\\n     *\\n     * @param usdcAmount  Number of USDC tokens to commit\\n     * @return lpAmount  Number of LP USDC/MAI tokens committed\\n     */\\n    function _zapIn(UsdcQuantity usdcAmount) internal returns (LpQuantity lpAmount) {\\n        MaiQuantity maiAmount;\\n\\n        (usdcAmount, maiAmount) = _splitUSDC(usdcAmount);\\n        lpAmount = _addLiquidity(usdcAmount, maiAmount);\\n        _stakeLP(lpAmount);\\n    }\\n\\n    /**\\n     * Extract the given number of LP USDC/MAI tokens\\n     *\\n     * This method will:\\n     *   1. unstake the given number of LP USDC/MAI tokens from QuiDao's Farm,\\n     *   2. remove the liquidity provided by the given number of LP USDC/MAI tokens from the liquidity pool, and\\n     *   3. convert the MAI tokens back into USDC tokens.\\n     *\\n     * @param lpAmount  Number of LP USDC/MAI tokens to extract\\n     * @return usdcAmount  Number of extracted USDC tokens\\n     */\\n    function _zapOut(LpQuantity lpAmount) internal returns (UsdcQuantity usdcAmount) {\\n        MaiQuantity maiAmount;\\n\\n        _unstakeLP(lpAmount);\\n        (usdcAmount, maiAmount) = _removeLiquidity(lpAmount);\\n        usdcAmount = _unsplitUSDC(usdcAmount, maiAmount);\\n    }\\n\\n    /**\\n     * Given a USDC token amount, split a portion of it into MAI tokens so as to provide balanced liquidity\\n     *\\n     * @param amount  Number of USDC tokens to split\\n     * @return usdcAmount  Number of resulting USDC tokens\\n     * @return maiAmount  Number of resulting MAI tokens\\n     */\\n    function _splitUSDC(UsdcQuantity amount) internal returns (UsdcQuantity usdcAmount, MaiQuantity maiAmount) {\\n        (UsdcQuantity usdcReserves, ) = _getLpReserves();\\n        UsdcQuantity amountToSwap = _calculateSwapInAmount(usdcReserves, amount);\\n\\n        require(lt(UsdcQuantity.wrap(0), amountToSwap), \\\"Nothing to swap\\\");\\n\\n        maiAmount = _swapTokens(amountToSwap);\\n        usdcAmount = sub(amount, amountToSwap);\\n    }\\n\\n    /**\\n     * Given a USDC token amount and a MAI token amount, swap MAIs into USDCs and consolidate\\n     *\\n     * @param amount  Number of USDC tokens to consolidate with\\n     * @param maiAmount  Number of MAI tokens to consolidate in\\n     * @return usdcAmount  Consolidated USDC amount\\n     */\\n    function _unsplitUSDC(UsdcQuantity amount, MaiQuantity maiAmount) internal returns (UsdcQuantity usdcAmount) {\\n        usdcAmount = add(amount, _swapTokens(maiAmount));\\n    }\\n\\n    /**\\n     * Add liquidity to the QuickSwap Liquidity Pool, as much as indicated by the given pair od USDC/MAI amounts\\n     *\\n     * @param usdcAmount  Number of USDC tokens to add\\n     * @param maiAmount  Number of MAI tokens to add\\n     * @return lpAmount  Number of LP USDC/MAI tokens obtained\\n     */\\n    function _addLiquidity(UsdcQuantity usdcAmount, MaiQuantity maiAmount) internal returns (LpQuantity lpAmount) {\\n        (, , uint256 _lpAmount) = IUniswapV2Router02(quickSwapRouterAddress).addLiquidity(\\n            usdcAddress,\\n            maiAddress,\\n            UsdcQuantity.unwrap(usdcAmount),\\n            MaiQuantity.unwrap(maiAmount),\\n            1,\\n            1,\\n            address(this),\\n            block.timestamp + ONE_HOUR\\n        );\\n        lpAmount = LpQuantity.wrap(_lpAmount);\\n    }\\n\\n    /**\\n     * Remove liquidity from the QuickSwap Liquidity Pool, as much as indicated by the given amount of LP tokens\\n     *\\n     * @param lpAmount  Number of LP USDC/MAI tokens to withdraw\\n     * @return usdcAmount  Number of USDC tokens withdrawn\\n     * @return maiAmount  Number of MAI tokens withdrawn\\n     */\\n    function _removeLiquidity(LpQuantity lpAmount) internal returns (UsdcQuantity usdcAmount, MaiQuantity maiAmount) {\\n        (uint256 _usdcAmount, uint256 _maiAmount) = IUniswapV2Router02(quickSwapRouterAddress).removeLiquidity(\\n            usdcAddress,\\n            maiAddress,\\n            LpQuantity.unwrap(lpAmount),\\n            1,\\n            1,\\n            address(this),\\n            block.timestamp + ONE_HOUR\\n        );\\n        (usdcAmount, maiAmount) = (UsdcQuantity.wrap(_usdcAmount), MaiQuantity.wrap(_maiAmount));\\n    }\\n\\n    /**\\n     * Deposit the given number of LP tokens into QiDao's Farm\\n     *\\n     * @param lpAmount  Number of LP USDC/MAI tokens to deposit into QiDao's Farm\\n     */\\n    function _stakeLP(LpQuantity lpAmount) internal {\\n        // --- Gas Saving -------------------------------------------------------------------------\\n        address _qiDaoFarmAddress = qiDaoFarmAddress;\\n\\n        IERC20(lpAddress).approve(_qiDaoFarmAddress, LpQuantity.unwrap(lpAmount));\\n        IFarm(_qiDaoFarmAddress).deposit(qiDaoPoolId, LpQuantity.unwrap(lpAmount));\\n    }\\n\\n    /**\\n     * Remove the given number of LP tokens from QiDao's Farm\\n     *\\n     * @param lpAmount  Number of LP USDC/MAI tokens to remove from QiDao's Farm\\n     */\\n    function _unstakeLP(LpQuantity lpAmount) internal {\\n        IFarm(qiDaoFarmAddress).withdraw(qiDaoPoolId, LpQuantity.unwrap(lpAmount));\\n    }\\n\\n    /**\\n     * Return the rewards accrued by staking LP USDC/MAI tokens in QiDao's Farm (in QI tokens)\\n     *\\n     * @return qiAmount  Number of QI tokens accrued\\n     */\\n    function _getPendingRewardsAmount() internal view returns (QiQuantity qiAmount) {\\n        // Get rewards on Farm\\n        qiAmount = QiQuantity.wrap(IFarm(qiDaoFarmAddress).pending(qiDaoPoolId, address(this)));\\n    }\\n\\n    /**\\n     * Swap the given number of MAI tokens to USDC\\n     *\\n     * @param maiAmount  Number of MAI tokens to swap\\n     * @return usdcAmount  Number of USDC tokens obtained\\n     */\\n    function _swapTokens(MaiQuantity maiAmount) internal returns (UsdcQuantity usdcAmount) {\\n        usdcAmount = UsdcQuantity.wrap(_swapTokens(maiAddress, usdcAddress, MaiQuantity.unwrap(maiAmount)));\\n    }\\n\\n    /**\\n     * Swap the given number of USDC tokens to MAI\\n     *\\n     * @param usdcAmount  Number of USDC tokens to swap\\n     * @return maiAmount  Number of MAI tokens obtained\\n     */\\n    function _swapTokens(UsdcQuantity usdcAmount) internal returns (MaiQuantity maiAmount) {\\n        maiAmount = MaiQuantity.wrap(_swapTokens(usdcAddress, maiAddress, UsdcQuantity.unwrap(usdcAmount)));\\n    }\\n\\n    /**\\n     * Swap the given number of QI tokens to USDC\\n     *\\n     * @param qiAmount  Number of QI tokens to swap\\n     * @return usdcAmount  Number of USDC tokens obtained\\n     */\\n    function _swapTokens(QiQuantity qiAmount) internal returns (UsdcQuantity usdcAmount) {\\n        usdcAmount = UsdcQuantity.wrap(_swapTokens(qiAddress, usdcAddress, QiQuantity.unwrap(qiAmount)));\\n    }\\n\\n    /**\\n     * Swap the given amount of tokens from the given \\\"from\\\" address to the given \\\"to\\\" address via QuickSwap, and return the amount of \\\"to\\\" tokens swapped\\n     *\\n     * @param fromAddress  Address to get swap tokens from\\n     * @param toAddress  Address to get swap tokens to\\n     * @param amount  Amount of tokens to swap (from)\\n     * @return swappedAmount  Amount of tokens deposited in addressTo\\n     */\\n    function _swapTokens(\\n        address fromAddress,\\n        address toAddress,\\n        uint256 amount\\n    ) internal returns (uint256 swappedAmount) {\\n        address[] memory path = new address[](2);\\n        (path[0], path[1]) = (fromAddress, toAddress);\\n\\n        swappedAmount = IUniswapV2Router02(quickSwapRouterAddress).swapExactTokensForTokens(amount, 1, path, address(this), block.timestamp + ONE_HOUR)[1];\\n    }\\n\\n    // --------------------------------------------------------------------------------------------------------------------------------------------------------\\n    // --- UniSwap Simulation ---------------------------------------------------------------------------------------------------------------------------------\\n    // --------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\n    function _calculateSwapInAmount(UsdcQuantity reserveIn, UsdcQuantity userIn) internal pure returns (UsdcQuantity amount) {\\n        amount = sub(sqrt(mulDiv(add(mul(3988009, reserveIn), mul(3988000, userIn)), reserveIn, 3976036)), mulDiv(reserveIn, 1997, 1994));\\n    }\\n\\n    function _getAmountOut(\\n        uint256 amountIn,\\n        uint256 reserveIn,\\n        uint256 reserveOut\\n    ) internal pure returns (uint256 amountOut) {\\n        uint256 amountInWithFee = amountIn * 997;\\n        amountOut = Math.mulDiv(amountInWithFee, reserveOut, reserveIn * 1000 + amountInWithFee);\\n    }\\n\\n    function _getAmountOut(\\n        MaiQuantity amountIn,\\n        MaiQuantity reserveIn,\\n        UsdcQuantity reserveOut\\n    ) internal pure returns (UsdcQuantity) {\\n        return UsdcQuantity.wrap(_getAmountOut(MaiQuantity.unwrap(amountIn), MaiQuantity.unwrap(reserveIn), UsdcQuantity.unwrap(reserveOut)));\\n    }\\n\\n    function _getAmountOut(\\n        UsdcQuantity amountIn,\\n        UsdcQuantity reserveIn,\\n        MaiQuantity reserveOut\\n    ) internal pure returns (MaiQuantity amountOut) {\\n        return MaiQuantity.wrap(_getAmountOut(UsdcQuantity.unwrap(amountIn), UsdcQuantity.unwrap(reserveIn), MaiQuantity.unwrap(reserveOut)));\\n    }\\n}\\n\",\"keccak256\":\"0x4bb2f813dcc3307443d6bd1688697129f59d063967ce0a7055072733697d3986\",\"license\":\"MIT\"},\"contracts/PeronioSupport.sol\":{\"content\":\"pragma solidity ^0.8.17;\\n\\n// SPDX-License-Identifier: MIT\\n\\nimport \\\"./IPeronioSupport.sol\\\";\\n\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n// --- Implementation-side user defined value types -----------------------------------------------------------------------------------------------------------\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\ntype UniSwapKQuantity is uint256;\\ntype UniSwapRootKQuantity is uint256;\\ntype UsdcSqQuantity is uint256;\\ntype RatioWith4Decimals is uint256;\\n\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n// --- Standard Numeric Types ---------------------------------------------------------------------------------------------------------------------------------\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n//\\n// Standard Numeric Types (SNTs) can be operated with in the same manner as \\\"normal\\\" numeric types can.\\n// This means that SNTs can:\\n//   - be added together,\\n//   - be subtracted from each other,\\n//   - be multiplied by a scalar value (only uint256 in this implementation) - both on the left and on the right,\\n//   - the minimum be calculated among them,\\n//   - the maximum be calculated among them,\\n//   - the \\\"==\\\", \\\"!=\\\", \\\"<=\\\", \\\"<\\\", \\\">\\\", and \\\">=\\\" relations established between them, and\\n// The mulDiv() interactions will be taken care of later.\\n//\\n\\n// --- UniSwap K ----------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(UniSwapKQuantity.unwrap(left) + UniSwapKQuantity.unwrap(right));\\n}\\n\\nfunction sub(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(UniSwapKQuantity.unwrap(left) - UniSwapKQuantity.unwrap(right));\\n}\\n\\nfunction mul(UniSwapKQuantity val, uint256 x) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(UniSwapKQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, UniSwapKQuantity val) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(x * UniSwapKQuantity.unwrap(val));\\n}\\n\\nfunction min(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.min(UniSwapKQuantity.unwrap(left), UniSwapKQuantity.unwrap(right)));\\n}\\n\\nfunction max(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.max(UniSwapKQuantity.unwrap(left), UniSwapKQuantity.unwrap(right)));\\n}\\n\\nfunction eq(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (bool) {\\n    return UniSwapKQuantity.unwrap(left) == UniSwapKQuantity.unwrap(right);\\n}\\n\\nfunction neq(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (bool) {\\n    return UniSwapKQuantity.unwrap(left) != UniSwapKQuantity.unwrap(right);\\n}\\n\\nfunction lt(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (bool) {\\n    return UniSwapKQuantity.unwrap(left) < UniSwapKQuantity.unwrap(right);\\n}\\n\\nfunction gt(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (bool) {\\n    return UniSwapKQuantity.unwrap(left) > UniSwapKQuantity.unwrap(right);\\n}\\n\\nfunction lte(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (bool) {\\n    return UniSwapKQuantity.unwrap(left) <= UniSwapKQuantity.unwrap(right);\\n}\\n\\nfunction gte(UniSwapKQuantity left, UniSwapKQuantity right) pure returns (bool) {\\n    return UniSwapKQuantity.unwrap(left) >= UniSwapKQuantity.unwrap(right);\\n}\\n\\n// --- UniSwap rootK ------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(UniSwapRootKQuantity.unwrap(left) + UniSwapRootKQuantity.unwrap(right));\\n}\\n\\nfunction sub(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(UniSwapRootKQuantity.unwrap(left) - UniSwapRootKQuantity.unwrap(right));\\n}\\n\\nfunction mul(UniSwapRootKQuantity val, uint256 x) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(UniSwapRootKQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, UniSwapRootKQuantity val) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(x * UniSwapRootKQuantity.unwrap(val));\\n}\\n\\nfunction min(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.min(UniSwapRootKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right)));\\n}\\n\\nfunction max(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.max(UniSwapRootKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right)));\\n}\\n\\nfunction eq(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (bool) {\\n    return UniSwapRootKQuantity.unwrap(left) == UniSwapRootKQuantity.unwrap(right);\\n}\\n\\nfunction neq(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (bool) {\\n    return UniSwapRootKQuantity.unwrap(left) != UniSwapRootKQuantity.unwrap(right);\\n}\\n\\nfunction lt(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (bool) {\\n    return UniSwapRootKQuantity.unwrap(left) < UniSwapRootKQuantity.unwrap(right);\\n}\\n\\nfunction gt(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (bool) {\\n    return UniSwapRootKQuantity.unwrap(left) > UniSwapRootKQuantity.unwrap(right);\\n}\\n\\nfunction lte(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (bool) {\\n    return UniSwapRootKQuantity.unwrap(left) <= UniSwapRootKQuantity.unwrap(right);\\n}\\n\\nfunction gte(UniSwapRootKQuantity left, UniSwapRootKQuantity right) pure returns (bool) {\\n    return UniSwapRootKQuantity.unwrap(left) >= UniSwapRootKQuantity.unwrap(right);\\n}\\n\\n// --- USDC-squared -------------------------------------------------------------------------------------------------------------------------------------------\\nfunction add(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(UsdcSqQuantity.unwrap(left) + UsdcSqQuantity.unwrap(right));\\n}\\n\\nfunction sub(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(UsdcSqQuantity.unwrap(left) - UsdcSqQuantity.unwrap(right));\\n}\\n\\nfunction mul(UsdcSqQuantity val, uint256 x) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(UsdcSqQuantity.unwrap(val) * x);\\n}\\n\\nfunction mul(uint256 x, UsdcSqQuantity val) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(x * UsdcSqQuantity.unwrap(val));\\n}\\n\\nfunction min(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.min(UsdcSqQuantity.unwrap(left), UsdcSqQuantity.unwrap(right)));\\n}\\n\\nfunction max(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.max(UsdcSqQuantity.unwrap(left), UsdcSqQuantity.unwrap(right)));\\n}\\n\\nfunction eq(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (bool) {\\n    return UsdcSqQuantity.unwrap(left) == UsdcSqQuantity.unwrap(right);\\n}\\n\\nfunction neq(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (bool) {\\n    return UsdcSqQuantity.unwrap(left) != UsdcSqQuantity.unwrap(right);\\n}\\n\\nfunction lt(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (bool) {\\n    return UsdcSqQuantity.unwrap(left) < UsdcSqQuantity.unwrap(right);\\n}\\n\\nfunction gt(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (bool) {\\n    return UsdcSqQuantity.unwrap(left) > UsdcSqQuantity.unwrap(right);\\n}\\n\\nfunction lte(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (bool) {\\n    return UsdcSqQuantity.unwrap(left) <= UsdcSqQuantity.unwrap(right);\\n}\\n\\nfunction gte(UsdcSqQuantity left, UsdcSqQuantity right) pure returns (bool) {\\n    return UsdcSqQuantity.unwrap(left) >= UsdcSqQuantity.unwrap(right);\\n}\\n\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n// --- USDC-squared quantities --------------------------------------------------------------------------------------------------------------------------------\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\nfunction sqrt(UsdcSqQuantity x) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.sqrt(UsdcSqQuantity.unwrap(x)));\\n}\\n\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n// --- UniSwap K-values ---------------------------------------------------------------------------------------------------------------------------------------\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\nfunction mul(UsdcQuantity left, MaiQuantity right) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(UsdcQuantity.unwrap(left) * MaiQuantity.unwrap(right));\\n}\\n\\nfunction sqrt(UniSwapKQuantity x) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.sqrt(UniSwapKQuantity.unwrap(x)));\\n}\\n\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n// --- Ratio conversion ---------------------------------------------------------------------------------------------------------------------------------------\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\nfunction ratio4to6(RatioWith4Decimals x) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(RatioWith4Decimals.unwrap(x) * 10**2);\\n}\\n\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n// --- MulDiv Interactions ------------------------------------------------------------------------------------------------------------------------------------\\n// ------------------------------------------------------------------------------------------------------------------------------------------------------------\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    RatioWith4Decimals right,\\n    LpQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(LpQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UniSwapKQuantity right,\\n    LpQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UniSwapRootKQuantity right,\\n    LpQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UsdcSqQuantity right,\\n    LpQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    LpQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(LpQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    RatioWith4Decimals right,\\n    MaiQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(MaiQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UniSwapKQuantity right,\\n    MaiQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UniSwapRootKQuantity right,\\n    MaiQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(MaiQuantity.unwrap(left), UsdcQuantity.unwrap(right), UniSwapKQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcQuantity right,\\n    uint256 div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcSqQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcSqQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    MaiQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(MaiQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    RatioWith4Decimals right,\\n    PePerUsdcQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UniSwapKQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UniSwapRootKQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcSqQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PePerUsdcQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(PePerUsdcQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    RatioWith4Decimals right,\\n    PeQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(PeQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UniSwapKQuantity right,\\n    PeQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UniSwapRootKQuantity right,\\n    PeQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UsdcSqQuantity right,\\n    PeQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    PeQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(PeQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    RatioWith4Decimals right,\\n    QiQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(QiQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UniSwapKQuantity right,\\n    QiQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UniSwapRootKQuantity right,\\n    QiQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UsdcSqQuantity right,\\n    QiQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    QiQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(QiQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    LpQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), LpQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    MaiQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), MaiQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    PePerUsdcQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), PePerUsdcQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    PeQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), PeQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    QiQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), QiQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    RatioWith6Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UniSwapKQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UniSwapKQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UniSwapRootKQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UniSwapRootKQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UsdcPerPeQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UsdcPerPeQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UsdcQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UsdcQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UsdcSqQuantity right,\\n    RatioWith4Decimals div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UsdcSqQuantity.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    uint256 right,\\n    RatioWith4Decimals div\\n) pure returns (uint256) {\\n    return Math.mulDiv(RatioWith4Decimals.unwrap(left), right, RatioWith4Decimals.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    RatioWith4Decimals left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith4Decimals.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    RatioWith4Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UniSwapKQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UniSwapKQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UniSwapRootKQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UniSwapRootKQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UsdcSqQuantity right,\\n    RatioWith6Decimals div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UsdcSqQuantity.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    RatioWith6Decimals left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(RatioWith6Decimals.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    LpQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), LpQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    MaiQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), MaiQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    PePerUsdcQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    PeQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), PeQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    QiQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), QiQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    RatioWith4Decimals right,\\n    UniSwapKQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    RatioWith6Decimals right,\\n    UniSwapKQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UsdcPerPeQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UsdcQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UsdcQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UsdcQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UsdcQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UsdcQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UsdcSqQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    uint256 right,\\n    MaiQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), right, MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    uint256 right,\\n    UniSwapKQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(UniSwapKQuantity.unwrap(left), right, UniSwapKQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    uint256 right,\\n    UniSwapRootKQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), right, UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    uint256 right,\\n    UsdcQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), right, UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapKQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapKQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    LpQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), LpQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    MaiQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), MaiQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    PePerUsdcQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    PeQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), PeQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    QiQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), QiQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    RatioWith4Decimals right,\\n    UniSwapRootKQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    RatioWith6Decimals right,\\n    UniSwapRootKQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UniSwapRootKQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UniSwapRootKQuantity right,\\n    UsdcQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UniSwapRootKQuantity right,\\n    uint256 div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UsdcPerPeQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UsdcQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UsdcQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UsdcSqQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    uint256 right,\\n    UniSwapRootKQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(UniSwapRootKQuantity.unwrap(left), right, UniSwapRootKQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    UniSwapRootKQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UniSwapRootKQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    RatioWith4Decimals right,\\n    UsdcPerPeQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UniSwapKQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UniSwapRootKQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcPerPeQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcPerPeQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    MaiQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(UsdcQuantity.unwrap(left), MaiQuantity.unwrap(right), UniSwapKQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    MaiQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), MaiQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    MaiQuantity right,\\n    uint256 div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), MaiQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    RatioWith4Decimals right,\\n    UsdcQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UniSwapKQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UniSwapKQuantity right,\\n    UsdcQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UniSwapKQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UniSwapRootKQuantity right,\\n    UsdcQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UsdcQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(UsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcSqQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UsdcQuantity right,\\n    uint256 div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UsdcQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    LpQuantity right,\\n    LpQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), LpQuantity.unwrap(right), LpQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    LpQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (LpQuantity) {\\n    return LpQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), LpQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    MaiQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), MaiQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    MaiQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), MaiQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    MaiQuantity right,\\n    UsdcQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), MaiQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    MaiQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), MaiQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    PePerUsdcQuantity right,\\n    PePerUsdcQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), PePerUsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    PePerUsdcQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (PePerUsdcQuantity) {\\n    return PePerUsdcQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), PePerUsdcQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    PeQuantity right,\\n    PeQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), PeQuantity.unwrap(right), PeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    PeQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (PeQuantity) {\\n    return PeQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), PeQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    QiQuantity right,\\n    QiQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), QiQuantity.unwrap(right), QiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    QiQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (QiQuantity) {\\n    return QiQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), QiQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    RatioWith4Decimals right,\\n    UsdcSqQuantity div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), RatioWith4Decimals.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    RatioWith6Decimals right,\\n    RatioWith6Decimals div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), RatioWith6Decimals.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    RatioWith6Decimals right,\\n    UsdcSqQuantity div\\n) pure returns (RatioWith6Decimals) {\\n    return RatioWith6Decimals.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), RatioWith6Decimals.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UniSwapKQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UniSwapKQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UniSwapRootKQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UniSwapRootKQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcPerPeQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcPerPeQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UsdcPerPeQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UsdcPerPeQuantity) {\\n    return UsdcPerPeQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UsdcPerPeQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UsdcQuantity right,\\n    UsdcQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UsdcQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UsdcQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    uint256 right,\\n    UsdcQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), right, UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    uint256 right,\\n    UsdcSqQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(UsdcSqQuantity.unwrap(left), right, UsdcSqQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    UsdcSqQuantity left,\\n    uint256 right,\\n    uint256 div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(UsdcSqQuantity.unwrap(left), right, div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    RatioWith4Decimals right,\\n    RatioWith4Decimals div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, RatioWith4Decimals.unwrap(right), RatioWith4Decimals.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    RatioWith4Decimals right,\\n    uint256 div\\n) pure returns (RatioWith4Decimals) {\\n    return RatioWith4Decimals.wrap(Math.mulDiv(left, RatioWith4Decimals.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UniSwapKQuantity right,\\n    MaiQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(left, UniSwapKQuantity.unwrap(right), MaiQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UniSwapKQuantity right,\\n    UniSwapKQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, UniSwapKQuantity.unwrap(right), UniSwapKQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UniSwapKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(left, UniSwapKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UniSwapKQuantity right,\\n    UsdcQuantity div\\n) pure returns (MaiQuantity) {\\n    return MaiQuantity.wrap(Math.mulDiv(left, UniSwapKQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UniSwapKQuantity right,\\n    uint256 div\\n) pure returns (UniSwapKQuantity) {\\n    return UniSwapKQuantity.wrap(Math.mulDiv(left, UniSwapKQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UniSwapRootKQuantity right,\\n    UniSwapRootKQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, UniSwapRootKQuantity.unwrap(right), UniSwapRootKQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UniSwapRootKQuantity right,\\n    uint256 div\\n) pure returns (UniSwapRootKQuantity) {\\n    return UniSwapRootKQuantity.wrap(Math.mulDiv(left, UniSwapRootKQuantity.unwrap(right), div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UsdcSqQuantity right,\\n    UsdcQuantity div\\n) pure returns (UsdcQuantity) {\\n    return UsdcQuantity.wrap(Math.mulDiv(left, UsdcSqQuantity.unwrap(right), UsdcQuantity.unwrap(div)));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UsdcSqQuantity right,\\n    UsdcSqQuantity div\\n) pure returns (uint256) {\\n    return Math.mulDiv(left, UsdcSqQuantity.unwrap(right), UsdcSqQuantity.unwrap(div));\\n}\\n\\nfunction mulDiv(\\n    uint256 left,\\n    UsdcSqQuantity right,\\n    uint256 div\\n) pure returns (UsdcSqQuantity) {\\n    return UsdcSqQuantity.wrap(Math.mulDiv(left, UsdcSqQuantity.unwrap(right), div));\\n}\\n\",\"keccak256\":\"0xa840f90c5b743932900e38232c91c8728d1f9408f24db3e9ec54f65014e797a5\",\"license\":\"MIT\"},\"contracts/qidao/IFarm.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\ninterface IFarm {\\n    function add(\\n        uint256 _allocPoint,\\n        address _lpToken,\\n        bool _withUpdate,\\n        uint16 _depositFeeBP\\n    ) external;\\n\\n    function deposit(uint256 _pid, uint256 _amount) external;\\n\\n    function deposited(uint256 _pid, address _user) external view returns (uint256);\\n\\n    function emergencyWithdraw(uint256 _pid) external;\\n\\n    function endBlock() external view returns (uint256);\\n\\n    function erc20() external view returns (address);\\n\\n    function feeAddress() external view returns (address);\\n\\n    function fund(uint256 _amount) external;\\n\\n    function massUpdatePools() external;\\n\\n    function owner() external view returns (address);\\n\\n    function paidOut() external view returns (uint256);\\n\\n    function pending(uint256 _pid, address _user) external view returns (uint256);\\n\\n    function poolInfo(uint256)\\n        external\\n        view\\n        returns (\\n            address lpToken,\\n            uint256 allocPoint,\\n            uint256 lastRewardBlock,\\n            uint256 accERC20PerShare,\\n            uint16 depositFeeBP\\n        );\\n\\n    function poolLength() external view returns (uint256);\\n\\n    function renounceOwnership() external;\\n\\n    function rewardPerBlock() external view returns (uint256);\\n\\n    function set(\\n        uint256 _pid,\\n        uint256 _allocPoint,\\n        bool _withUpdate\\n    ) external;\\n\\n    function setFeeAddress(address _feeAddress) external;\\n\\n    function startBlock() external view returns (uint256);\\n\\n    function totalAllocPoint() external view returns (uint256);\\n\\n    function totalPending() external view returns (uint256);\\n\\n    function transferOwnership(address newOwner) external;\\n\\n    function updatePool(uint256 _pid) external;\\n\\n    function userInfo(uint256, address) external view returns (uint256 amount, uint256 rewardDebt);\\n\\n    function withdraw(uint256 _pid, uint256 _amount) external;\\n}\\n\",\"keccak256\":\"0xa9f4ab1afb324e3be8c35fa310fd8c23b614349487f606c9b4dcb8408b8e9a06\",\"license\":\"MIT\"},\"contracts/uniswap/interfaces/IERC20Uniswap.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.17;\\n\\ninterface IERC20Uniswap {\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    function name() external view returns (string memory);\\n\\n    function symbol() external view returns (string memory);\\n\\n    function decimals() external view returns (uint8);\\n\\n    function totalSupply() external view returns (uint256);\\n\\n    function balanceOf(address owner) external view returns (uint256);\\n\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    function approve(address spender, uint256 value) external returns (bool);\\n\\n    function transfer(address to, uint256 value) external returns (bool);\\n\\n    function transferFrom(\\n        address from,\\n        address to,\\n        uint256 value\\n    ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x667e2925be913b69db034b03fa1ce3606bd947d74520ba0313a70f32d0cab88a\",\"license\":\"GPL-3.0\"},\"contracts/uniswap/interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.17;\\n\\ninterface IUniswapV2Pair {\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    function NAME() external pure returns (string memory);\\n\\n    function SYMBOL() external pure returns (string memory);\\n\\n    function DECIMALS() external pure returns (uint8);\\n\\n    function totalSupply() external view returns (uint256);\\n\\n    function balanceOf(address owner) external view returns (uint256);\\n\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    function approve(address spender, uint256 value) external returns (bool);\\n\\n    function transfer(address to, uint256 value) external returns (bool);\\n\\n    function transferFrom(\\n        address from,\\n        address to,\\n        uint256 value\\n    ) external returns (bool);\\n\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    function nonces(address owner) external view returns (uint256);\\n\\n    function permit(\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external;\\n\\n    event Mint(address indexed sender, uint256 amount0, uint256 amount1);\\n    event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);\\n    event Swap(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to);\\n    event Sync(uint112 reserve0, uint112 reserve1);\\n\\n    function MINIMUM_LIQUIDITY() external pure returns (uint256);\\n\\n    function factory() external view returns (address);\\n\\n    function token0() external view returns (address);\\n\\n    function token1() external view returns (address);\\n\\n    function getReserves()\\n        external\\n        view\\n        returns (\\n            uint112 reserve0,\\n            uint112 reserve1,\\n            uint32 blockTimestampLast\\n        );\\n\\n    function price0CumulativeLast() external view returns (uint256);\\n\\n    function price1CumulativeLast() external view returns (uint256);\\n\\n    function kLast() external view returns (uint256);\\n\\n    function mint(address to) external returns (uint256 liquidity);\\n\\n    function burn(address to) external returns (uint256 amount0, uint256 amount1);\\n\\n    function swap(\\n        uint256 amount0Out,\\n        uint256 amount1Out,\\n        address to,\\n        bytes calldata data\\n    ) external;\\n\\n    function skim(address to) external;\\n\\n    function sync() external;\\n\\n    function initialize(address, address) external;\\n}\\n\",\"keccak256\":\"0x5be83d2f9dcded80ff5ae74ca2544b58110b2a2e67ea1cc8d832aefe202ee168\",\"license\":\"GPL-3.0\"},\"contracts/uniswap/interfaces/IUniswapV2Router01.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.17;\\n\\ninterface IUniswapV2Router01 {\\n    function factory() external view returns (address);\\n\\n    function WETH() external view returns (address);\\n\\n    function addLiquidity(\\n        address tokenA,\\n        address tokenB,\\n        uint256 amountADesired,\\n        uint256 amountBDesired,\\n        uint256 amountAMin,\\n        uint256 amountBMin,\\n        address to,\\n        uint256 deadline\\n    )\\n        external\\n        returns (\\n            uint256 amountA,\\n            uint256 amountB,\\n            uint256 liquidity\\n        );\\n\\n    function addLiquidityETH(\\n        address token,\\n        uint256 amountTokenDesired,\\n        uint256 amountTokenMin,\\n        uint256 amountETHMin,\\n        address to,\\n        uint256 deadline\\n    )\\n        external\\n        payable\\n        returns (\\n            uint256 amountToken,\\n            uint256 amountETH,\\n            uint256 liquidity\\n        );\\n\\n    function removeLiquidity(\\n        address tokenA,\\n        address tokenB,\\n        uint256 liquidity,\\n        uint256 amountAMin,\\n        uint256 amountBMin,\\n        address to,\\n        uint256 deadline\\n    ) external returns (uint256 amountA, uint256 amountB);\\n\\n    function removeLiquidityETH(\\n        address token,\\n        uint256 liquidity,\\n        uint256 amountTokenMin,\\n        uint256 amountETHMin,\\n        address to,\\n        uint256 deadline\\n    ) external returns (uint256 amountToken, uint256 amountETH);\\n\\n    function removeLiquidityWithPermit(\\n        address tokenA,\\n        address tokenB,\\n        uint256 liquidity,\\n        uint256 amountAMin,\\n        uint256 amountBMin,\\n        address to,\\n        uint256 deadline,\\n        bool approveMax,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external returns (uint256 amountA, uint256 amountB);\\n\\n    function removeLiquidityETHWithPermit(\\n        address token,\\n        uint256 liquidity,\\n        uint256 amountTokenMin,\\n        uint256 amountETHMin,\\n        address to,\\n        uint256 deadline,\\n        bool approveMax,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external returns (uint256 amountToken, uint256 amountETH);\\n\\n    function swapExactTokensForTokens(\\n        uint256 amountIn,\\n        uint256 amountOutMin,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external returns (uint256[] memory amounts);\\n\\n    function swapTokensForExactTokens(\\n        uint256 amountOut,\\n        uint256 amountInMax,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external returns (uint256[] memory amounts);\\n\\n    function swapExactETHForTokens(\\n        uint256 amountOutMin,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external payable returns (uint256[] memory amounts);\\n\\n    function swapTokensForExactETH(\\n        uint256 amountOut,\\n        uint256 amountInMax,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external returns (uint256[] memory amounts);\\n\\n    function swapExactTokensForETH(\\n        uint256 amountIn,\\n        uint256 amountOutMin,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external returns (uint256[] memory amounts);\\n\\n    function swapETHForExactTokens(\\n        uint256 amountOut,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external payable returns (uint256[] memory amounts);\\n\\n    function quote(\\n        uint256 amountA,\\n        uint256 reserveA,\\n        uint256 reserveB\\n    ) external pure returns (uint256 amountB);\\n\\n    function getAmountOut(\\n        uint256 amountIn,\\n        uint256 reserveIn,\\n        uint256 reserveOut\\n    ) external pure returns (uint256 amountOut);\\n\\n    function getAmountIn(\\n        uint256 amountOut,\\n        uint256 reserveIn,\\n        uint256 reserveOut\\n    ) external pure returns (uint256 amountIn);\\n\\n    function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);\\n\\n    function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);\\n}\\n\",\"keccak256\":\"0x19550e20bfe25f0566a0a286724d8931ddbcae5f97708ca0886c9b92cf52f80f\",\"license\":\"GPL-3.0\"},\"contracts/uniswap/interfaces/IUniswapV2Router02.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.17;\\n\\nimport \\\"./IUniswapV2Router01.sol\\\";\\n\\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\\n    function removeLiquidityETHSupportingFeeOnTransferTokens(\\n        address token,\\n        uint256 liquidity,\\n        uint256 amountTokenMin,\\n        uint256 amountETHMin,\\n        address to,\\n        uint256 deadline\\n    ) external returns (uint256 amountETH);\\n\\n    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\\n        address token,\\n        uint256 liquidity,\\n        uint256 amountTokenMin,\\n        uint256 amountETHMin,\\n        address to,\\n        uint256 deadline,\\n        bool approveMax,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external returns (uint256 amountETH);\\n\\n    function swapExactTokensForTokensSupportingFeeOnTransferTokens(\\n        uint256 amountIn,\\n        uint256 amountOutMin,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external;\\n\\n    function swapExactETHForTokensSupportingFeeOnTransferTokens(\\n        uint256 amountOutMin,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external payable;\\n\\n    function swapExactTokensForETHSupportingFeeOnTransferTokens(\\n        uint256 amountIn,\\n        uint256 amountOutMin,\\n        address[] calldata path,\\n        address to,\\n        uint256 deadline\\n    ) external;\\n}\\n\",\"keccak256\":\"0x4584034b5885c8e34633bb861975ab410ca6ef5d1f684f17c20389d5409df56d\",\"license\":\"GPL-3.0\"}},\"version\":1}",
  "bytecode": "0x61022060405261c3506009556105dc600a553480156200001e57600080fd5b5060405162004ca338038062004ca3833981016040819052620000419162000318565b604051806040016040528060078152602001665065726f6e696f60c81b81525080604051806040016040528060018152602001603160f81b815250604051806040016040528060078152602001665065726f6e696f60c81b815250604051806040016040528060018152602001600560fc1b8152508160039081620000c7919062000449565b506004620000d6828262000449565b5050825160208085019190912083518483012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c0019052805194019390932091935091906080523060c05261012052505060016008555050506001600160a01b038781166101405286811661016052858116610180528381166101c0528281166101e05261020082905284166101a05233620001b560008262000247565b620001e17f74a064b2dec4aeb0b53e2d06f8e76ce531a17302a866fe51bc86d9a90b4e85e38262000247565b6200020d7f5407862f04286ebe607684514c14b7fffc750b6bf52ba44ea49569174845a5bd8262000247565b620002397f600e5f1c60beb469a3fa6dd3814a4ae211cc6259a6d033bae218a742f2af01d38262000247565b505050505050505062000515565b62000253828262000257565b5050565b60008281526007602090815260408083206001600160a01b038516845290915290205460ff16620002535760008281526007602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620002b73390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b03811681146200031357600080fd5b919050565b600080600080600080600060e0888a0312156200033457600080fd5b6200033f88620002fb565b96506200034f60208901620002fb565b95506200035f60408901620002fb565b94506200036f60608901620002fb565b93506200037f60808901620002fb565b92506200038f60a08901620002fb565b915060c0880151905092959891949750929550565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620003cf57607f821691505b602082108103620003f057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200044457600081815260208120601f850160051c810160208610156200041f5750805b601f850160051c820191505b8181101562000440578281556001016200042b565b5050505b505050565b81516001600160401b03811115620004655762000465620003a4565b6200047d81620004768454620003ba565b84620003f6565b602080601f831160018114620004b557600084156200049c5750858301515b600019600386901b1c1916600185901b17855562000440565b600085815260208120601f198616915b82811015620004e657888601518255948401946001909101908401620004c5565b5085821015620005055787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051610200516145cb620006d8600039600081816105ae015281816110c001528181611b8f01528181611c7a0152818161252201528181612aae0152613504015260008181610411015281816110ed01528181611bbe01528181611ca70152818161255101528181612ae1015261343b0152600081816105d501528181611772015281816131aa015281816133010152613890015260008181610496015281816111680152818161174601526129010152600081816106c40152818161090001528181610cce015281816112d3015281816117250152818161279701528181612986015261346c015260008181610635015281816116e30152818161281e01528181613349015281816138d801528181613c190152613c55015260008181610389015281816111fd0152818161170401528181611a7e01528181612084015281816128480152818161292201528181613328015281816138b701528181613bf80152613c7601526000612612015260006126610152600061263c01526000612595015260006125bf015260006125e901526145cb6000f3fe608060405234801561001057600080fd5b50600436106103575760003560e01c806373956bc3116101c8578063a524c99c11610104578063cedb9410116100a2578063dacee3471161007c578063dacee347146107c5578063dd62ed3e146107cd578063e4a3011614610806578063f3fef3a31461081957600080fd5b8063cedb94101461078c578063d505accf1461079f578063d547741f146107b257600080fd5b8063b4eae1cb116100de578063b4eae1cb1461074d578063c00c9f7f14610755578063ca4fb87c1461075d578063cb6290091461078457600080fd5b8063a524c99c1461070a578063a9059cbb1461071d578063b282e0f91461073057600080fd5b80638f839603116101715780639b4dc8cc1161014b5780639b4dc8cc146106bf5780639d938db0146106e6578063a217fddf146106ef578063a457c2d7146106f757600080fd5b80638f8396031461065757806391d148541461067e57806395d89b41146106b757600080fd5b80637a9b71f9116101a25780637a9b71f91461060a5780637ecebe001461061d578063804bbdc61461063057600080fd5b806373956bc3146105a9578063776429e7146105d057806379cc6790146105f757600080fd5b8063313ce5671161029757806342966c68116102405780635b9f00161161021a5780635b9f0016146105495780635da0d90a146105515780636fae2e151461055957806370a082311461058057600080fd5b806342966c681461051a5780635204363e1461052d57806354cf2aeb1461054057600080fd5b806336568abe1161027157806336568abe146104ec57806339509351146104ff578063399c04251461051257600080fd5b8063313ce567146104cd57806335092dad146104dc5780633644e515146104e457600080fd5b8063156e29f61161030457806323b872dd116102de57806323b872dd1461045b578063248a9ca31461046e57806326d71f1e146104915780632f2ff15d146104b857600080fd5b8063156e29f614610433578063158ef93e1461044657806318160ddd1461045357600080fd5b806306fdde031161033557806306fdde03146103e4578063095ea7b3146103f95780630c7c6f011461040c57600080fd5b806301ffc9a71461035c57806302d454571461038457806306d47de9146103c3575b600080fd5b61036f61036a366004613e1c565b61082c565b60405190151581526020015b60405180910390f35b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161037b565b6103d66103d1366004613e5b565b610870565b60405190815260200161037b565b6103ec610980565b60405161037b9190613eab565b61036f610407366004613e5b565b610a12565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6103d6610441366004613ede565b610a2a565b600b5461036f9060ff1681565b6002546103d6565b61036f610469366004613f13565b610aa1565b6103d661047c366004613f54565b60009081526007602052604090206001015490565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6104cb6104c6366004613f6d565b610ac7565b005b6040516006815260200161037b565b6103d6610af1565b6103d6610b00565b6104cb6104fa366004613f6d565b610b0a565b61036f61050d366004613e5b565b610b96565b6103d6610bd5565b6104cb610528366004613f54565b610c05565b6103d661053b366004613ede565b610c12565b6103d6600a5481565b6103d6610ca1565b6103d6610cab565b6103d67f600e5f1c60beb469a3fa6dd3814a4ae211cc6259a6d033bae218a742f2af01d381565b6103d661058e366004613f9d565b6001600160a01b031660009081526020819052604090205490565b6103d67f000000000000000000000000000000000000000000000000000000000000000081565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6104cb610605366004613e5b565b610cb5565b6103d6610618366004613f54565b610cca565b6103d661062b366004613f9d565b610ee2565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6103d67f74a064b2dec4aeb0b53e2d06f8e76ce531a17302a866fe51bc86d9a90b4e85e381565b61036f61068c366004613f6d565b60009182526007602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6103ec610f00565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6103d660095481565b6103d6600081565b61036f610705366004613e5b565b610f0f565b6103d6610718366004613f54565b610fc4565b61036f61072b366004613e5b565b611040565b61073861104e565b6040805192835260208301919091520161037b565b6103d6611062565b61073861106c565b6103d67f5407862f04286ebe607684514c14b7fffc750b6bf52ba44ea49569174845a5bd81565b6107386112c4565b6103d661079a366004613f54565b6112cf565b6104cb6107ad366004613fba565b6114cd565b6104cb6107c0366004613f6d565b611631565b6103d6611656565b6103d66107db366004614031565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6104cb61081436600461405f565b611677565b6103d6610827366004613e5b565b6119fc565b60006001600160e01b031982167f6ae1097800000000000000000000000000000000000000000000000000000000148061086a575061086a82611b00565b92915050565b60006002600854036108c95760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600855336108e8836108db611b67565b6108e3611c32565b611c3d565b91506108f382611c52565b6109276001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168584611d0e565b6109318184611d9f565b60408051838152602081018590526001600160a01b038316917e3acf01fc7fd0a8bbdc96cfc96b5ddb8fabb57027141a47a3f8ff8c06120517910160405180910390a250600160085592915050565b60606003805461098f90614081565b80601f01602080910402602001604051908101604052809291908181526020018280546109bb90614081565b8015610a085780601f106109dd57610100808354040283529160200191610a08565b820191906000526020600020905b8154815290600101906020018083116109eb57829003601f168201915b5050505050905090565b600033610a20818585611f24565b5060019392505050565b6000600260085403610a7e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108c0565b6002600881905550610a9484848460095461207c565b6001600855949350505050565b600033610aaf8582856121a5565b610aba858585612237565b60019150505b9392505050565b600082815260076020526040902060010154610ae28161244e565b610aec8383612458565b505050565b6000610afb6124fa565b905090565b6000610afb612588565b6001600160a01b0381163314610b885760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084016108c0565b610b9282826126af565b5050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190610a209082908690610bd09087906140cb565b611f24565b6000610afb610be2612732565b610bf9610bf16006600a6141c2565b60095461274b565b6108e36006600a6141c2565b610c0f3382611d9f565b50565b6000600260085403610c665760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108c0565b6002600855610c947f600e5f1c60beb469a3fa6dd3814a4ae211cc6259a6d033bae218a742f2af01d361244e565b610a94848484600061207c565b6000610afb611b67565b6000610afb612757565b610cc08233836121a5565b610b928282611d9f565b60007f00000000000000000000000000000000000000000000000000000000000000008180610cf761278f565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f91906141d1565b90506000610d75610d7085856128ca565b6128d6565b90506000610dde866001600160a01b0316637464fc3d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7091906141d1565b905080821115610e1657610e1383610e0e85610dfa86866128e1565b6108e3610e088860056128ca565b8761274b565b61274b565b92505b50506040516370a0823160e01b81526001600160a01b03851660048201819052600091610e9491906370a0823190602401602060405180830381865afa158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906141d1565b610e0e896108db611b67565b90506000610ea3858385611c3d565b90506000610eb2858486611c3d565b9050610ed582610e0e83610ec689866128e1565b610ed08b886128e1565b6128ed565b9998505050505050505050565b6001600160a01b03811660009081526005602052604081205461086a565b60606004805461098f90614081565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919083811015610fac5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016108c0565b610fb98286868403611f24565b506001949350505050565b6000610fef7f74a064b2dec4aeb0b53e2d06f8e76ce531a17302a866fe51bc86d9a90b4e85e361244e565b5060098054908290557f6f51444e6a490d4270634e3b854e9959ace1fc9b287af8677dfd06d4071f77be33604080516001600160a01b039092168252602082018590520160405180910390a1919050565b600033610a20818585612237565b60008061105961278f565b90939092509050565b6000610afb612732565b6000806110987f5407862f04286ebe607684514c14b7fffc750b6bf52ba44ea49569174845a5bd61244e565b6040517fe2bbb1580000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e2bbb15890604401600060405180830381600087803b15801561113957600080fd5b505af115801561114d573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506370a0823190602401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc91906141d1565b90506111e7816128fa565b506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561124c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127091906141d1565b925061127b83612947565b60408051838152602081018690529081018290529092507fc35d86b8f236816fab54de6cb4b564fc7abbe78e7fa53fc10a3e5ff4b28da8219060600160405180910390a1509091565b600080611059612973565b60007f000000000000000000000000000000000000000000000000000000000000000081806112fc61278f565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611340573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136491906141d1565b905060006113728488612a39565b905060006113818286866128ed565b905061138d858361274b565b945061139984826128e1565b935060006113b16113aa8a856128e1565b8688611c3d565b90508082106113ce576113c489846128e1565b92509050806113df565b60006113db838888611c3d565b9350505b5060006113ef610d7087876128ca565b90506000611434886001600160a01b0316637464fc3d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dba573d6000803e3d6000fd5b9050808211156114535761145085610e0e87610dfa86866128e1565b94505b5050600080611463838688611c3d565b9050600061147285878a611c3d565b905061147e8282612a7a565b9250505060006114a982610bf96006600a61149991906141c2565b6114a4600954612a86565b6128e1565b90506114bf816114b7611c32565b6108e3611b67565b9a9950505050505050505050565b8342111561151d5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e6500000060448201526064016108c0565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861154c8c612b78565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006115a782612b9e565b905060006115b782878787612c07565b9050896001600160a01b0316816001600160a01b03161461161a5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e6174757265000060448201526064016108c0565b6116258a8a8a611f24565b50505050505050505050565b60008281526007602052604090206001015461164c8161244e565b610aec83836126af565b6000610afb6116676006600a6141c2565b61166f611c32565b6108e3612757565b611681600061244e565b600b5460ff16156116d45760405162461bcd60e51b815260206004820152601c60248201527f436f6e747261637420616c726561647920696e697469616c697a65640000000060448201526064016108c0565b600b805460ff191660011790557f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600061176e3390565b90507f00000000000000000000000000000000000000000000000000000000000000006000196117a96001600160a01b03871684308c612c2f565b60405163095ea7b360e01b81526001600160a01b0383811660048301526024820183905288169063095ea7b3906044016020604051808303816000875af11580156117f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181c91906141ea565b5060405163095ea7b360e01b81526001600160a01b0383811660048301526024820183905287169063095ea7b3906044016020604051808303816000875af115801561186c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189091906141ea565b5060405163095ea7b360e01b81526001600160a01b0383811660048301526024820183905286169063095ea7b3906044016020604051808303816000875af11580156118e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190491906141ea565b5060405163095ea7b360e01b81526001600160a01b0383811660048301526024820183905285169063095ea7b3906044016020604051808303816000875af1158015611954573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197891906141ea565b5061198289612947565b5061198b612757565b98506119a7836119a28b8b6108e36006600a6141c2565b612c80565b604080516001600160a01b0385168152602081018b90529081018990527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050505050505050565b6000600260085403611a505760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108c0565b6002600855336000611a64846108db611b67565b9050611a6f81612d5f565b9250611aa56001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168685611d0e565b611aaf8285611d9f565b60408051848152602081018690526001600160a01b038416917fdf273cb619d95419a9cd0ec88123a0538c85064229baa6363788f743fff90deb910160405180910390a25050600160085592915050565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061086a57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461086a565b6040517fa23831060000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201523060248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a2383106906044015b602060405180830381865afa158015611c0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610afb91906141d1565b6000610afb60025490565b6000611c4a848484612d83565b949350505050565b6040517f441a3e700000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063441a3e7090604401600060405180830381600087803b158015611cf357600080fd5b505af1158015611d07573d6000803e3d6000fd5b5050505050565b6040516001600160a01b038316602482015260448101829052610aec9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152612e32565b6001600160a01b038216611e1b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b03821660009081526020819052604090205481811015611eaa5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b0383166000908152602081905260408120838303905560028054849290611ed990849061420c565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b038316611f9f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b03821661201b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000336120b47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316823088612c2f565b60006120be611b67565b905060006120e66120ce88612947565b610bf96120dd6006600a6141c2565b6114a489612a86565b90506120fa816120f4611c32565b84611c3d565b93508584101561214c5760405162461bcd60e51b815260206004820152601860248201527f4d696e696d756d207265717569726564206e6f74206d6574000000000000000060448201526064016108c0565b6121568885612c80565b60408051888152602081018690526001600160a01b038516917f25b428dfde728ccfaddad7e29e4ac23c24ed7fd1a6e3e3f91894a9a073f5dfff910160405180910390a2505050949350505050565b6001600160a01b03838116600090815260016020908152604080832093861683529290522054600019811461223157818110156122245760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016108c0565b6122318484848403611f24565b50505050565b6001600160a01b0383166122b35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b03821661232f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b038316600090815260208190526040902054818110156123be5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906123f59084906140cb565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161244191815260200190565b60405180910390a3612231565b610c0f8133612f17565b60008281526007602090815260408083206001600160a01b038516845290915290205460ff16610b925760008281526007602090815260408083206001600160a01b03851684529091529020805460ff191660011790556124b63390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6040517fe4c75c270000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201523060248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e4c75c2790604401611bf1565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156125e157507f000000000000000000000000000000000000000000000000000000000000000046145b1561260b57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60008281526007602090815260408083206001600160a01b038516845290915290205460ff1615610b925760008281526007602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610afb6127436006600a6141c2565b6108db612757565b6000610ac082846140cb565b600080600061276461278f565b91509150600080612773612973565b9150915061278682610e0e8386886128ed565b94505050505090565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156127f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128179190614242565b50915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161061289c57806dffffffffffffffffffffffffffff16826dffffffffffffffffffffffffffff166128bf565b816dffffffffffffffffffffffffffff16816dffffffffffffffffffffffffffff165b909590945092505050565b6000610ac08284614292565b600061086a82612f97565b6000610ac0828461420c565b6000611c4a8484846130fd565b600061086a7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084613138565b6000806129538361326b565b909350905061296283826132f4565b915061296d82613424565b50919050565b6000806000612980611b67565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a0691906141d1565b9050600080612a1361278f565b91509150612a22848385611c3d565b9550612a2f848285611c3d565b9450505050509091565b6000610ac0612a6b610d70612a61612a54623cda29886128ca565b610e0e623cda20886128ca565b86623cab64611c3d565b6114a4856107cd6107ca611c3d565b6000610ac08383613579565b6040517f1526fe270000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631526fe279060240160a060405180830381865afa158015612b28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4c91906142a9565b9450505050506000612b618261ffff1661358f565b9050611c4a84612b73600a548461274b565b61359c565b6001600160a01b038116600090815260056020526040902080546001810182559061296d565b600061086a612bab612588565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000612c18878787876135a8565b91509150612c2581613695565b5095945050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526122319085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611d53565b6001600160a01b038216612cd65760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016108c0565b8060026000828254612ce891906140cb565b90915550506001600160a01b03821660009081526020819052604081208054839290612d159084906140cb565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600080612d6b83611c52565b612d7483613881565b9092509050610ac082826139aa565b6000808060001985870985870292508281108382030391505080600003612dbd57838281612db357612db3614308565b0492505050610ac0565b808411612dc957600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000612e87826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139b99092919063ffffffff16565b805190915015610aec5780806020019051810190612ea591906141ea565b610aec5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108c0565b60008281526007602090815260408083206001600160a01b038516845290915290205460ff16610b9257612f55816001600160a01b031660146139c8565b612f608360206139c8565b604051602001612f7192919061431e565b60408051601f198184030181529082905262461bcd60e51b82526108c091600401613eab565b600081600003612fa957506000919050565b600182608081901c15612fc15760409190911b9060801c5b604081901c15612fd65760209190911b9060401c5b602081901c15612feb5760109190911b9060201c5b601081901c156130005760089190911b9060101c5b600881901c156130155760049190911b9060081c5b600481901c1561302a5760029190911b9060041c5b600281901c1561303c57600182901b91505b600182858161304d5761304d614308565b048301901c9150600182858161306557613065614308565b048301901c9150600182858161307d5761307d614308565b048301901c9150600182858161309557613095614308565b048301901c915060018285816130ad576130ad614308565b048301901c915060018285816130c5576130c5614308565b048301901c915060018285816130dd576130dd614308565b048301901c9150611c4a828386816130f7576130f7614308565b04613579565b60008061310c856103e5614292565b905061312f818481613120886103e8614292565b61312a91906140cb565b612d83565b95945050505050565b60408051600280825260608201835260009283929190602083019080368337019050509050848482600081518110613172576131726143b5565b602002602001018360018151811061318c5761318c6143b5565b6001600160a01b0393841660209182029290920101529181169091527f0000000000000000000000000000000000000000000000000000000000000000166338ed173984600184306131e0610e10426140cb565b6040518663ffffffff1660e01b81526004016132009594939291906143cb565b6000604051808303816000875af115801561321f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613247919081019061443c565b600181518110613259576132596143b5565b60200260200101519150509392505050565b600080600061327861278f565b50905060006132878286612a39565b9050806132d65760405162461bcd60e51b815260206004820152600f60248201527f4e6f7468696e6720746f2073776170000000000000000000000000000000000060448201526064016108c0565b6132df81613bf1565b92506132eb85826128e1565b93505050915091565b6000806001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e8e337007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000087876001803061337a610e10426140cb565b60405160e08a901b6001600160e01b03191681526001600160a01b039889166004820152968816602488015260448701959095526064860193909352608485019190915260a484015290921660c482015260e4810191909152610104016060604051808303816000875af11580156133f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061341a91906144fa565b9695505050505050565b60405163095ea7b360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000818116600484015260248301849052917f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af11580156134b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134db91906141ea565b506040517fe2bbb1580000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152602481018390526001600160a01b0382169063e2bbb15890604401600060405180830381600087803b15801561355d57600080fd5b505af1158015613571573d6000803e3d6000fd5b505050505050565b60008183106135885781610ac0565b5090919050565b600061086a826064614292565b6000610ac08383613c3e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156135df575060009050600361368c565b8460ff16601b141580156135f757508460ff16601c14155b15613608575060009050600461368c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561365c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166136855760006001925092505061368c565b9150600090505b94509492505050565b60008160048111156136a9576136a9614528565b036136b15750565b60018160048111156136c5576136c5614528565b036137125760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108c0565b600281600481111561372657613726614528565b036137735760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108c0565b600381600481111561378757613787614528565b036137fa5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b600481600481111561380e5761380e614528565b03610c0f5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b60008080806001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663baa2abde7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008860018030613908610e10426140cb565b60405160e089901b6001600160e01b03191681526001600160a01b039788166004820152958716602487015260448601949094526064850192909252608484015290921660a482015260c481019190915260e40160408051808303816000875af115801561397a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061399e919061453e565b90969095509350505050565b6000610ac083610e0e84613c4e565b6060611c4a8484600085613c9b565b606060006139d7836002614292565b6139e29060026140cb565b67ffffffffffffffff8111156139fa576139fa61439f565b6040519080825280601f01601f191660200182016040528015613a24576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613a5b57613a5b6143b5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613abe57613abe6143b5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000613afa846002614292565b613b059060016140cb565b90505b6001811115613ba2577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613b4657613b466143b5565b1a60f81b828281518110613b5c57613b5c6143b5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93613b9b81614562565b9050613b08565b508315610ac05760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108c0565b600061086a7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084613138565b6000818310156135885781610ac0565b600061086a7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084613138565b606082471015613d135760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b0385163b613d6a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108c0565b600080866001600160a01b03168587604051613d869190614579565b60006040518083038185875af1925050503d8060008114613dc3576040519150601f19603f3d011682016040523d82523d6000602084013e613dc8565b606091505b5091509150613dd8828286613de3565b979650505050505050565b60608315613df2575081610ac0565b825115613e025782518084602001fd5b8160405162461bcd60e51b81526004016108c09190613eab565b600060208284031215613e2e57600080fd5b81356001600160e01b031981168114610ac057600080fd5b6001600160a01b0381168114610c0f57600080fd5b60008060408385031215613e6e57600080fd5b8235613e7981613e46565b946020939093013593505050565b60005b83811015613ea2578181015183820152602001613e8a565b50506000910152565b6020815260008251806020840152613eca816040850160208701613e87565b601f01601f19169190910160400192915050565b600080600060608486031215613ef357600080fd5b8335613efe81613e46565b95602085013595506040909401359392505050565b600080600060608486031215613f2857600080fd5b8335613f3381613e46565b92506020840135613f4381613e46565b929592945050506040919091013590565b600060208284031215613f6657600080fd5b5035919050565b60008060408385031215613f8057600080fd5b823591506020830135613f9281613e46565b809150509250929050565b600060208284031215613faf57600080fd5b8135610ac081613e46565b600080600080600080600060e0888a031215613fd557600080fd5b8735613fe081613e46565b96506020880135613ff081613e46565b95506040880135945060608801359350608088013560ff8116811461401457600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561404457600080fd5b823561404f81613e46565b91506020830135613f9281613e46565b6000806040838503121561407257600080fd5b50508035926020909101359150565b600181811c9082168061409557607f821691505b60208210810361296d57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561086a5761086a6140b5565b600181815b808511156141195781600019048211156140ff576140ff6140b5565b8085161561410c57918102915b93841c93908002906140e3565b509250929050565b6000826141305750600161086a565b8161413d5750600061086a565b8160018114614153576002811461415d57614179565b600191505061086a565b60ff84111561416e5761416e6140b5565b50506001821b61086a565b5060208310610133831016604e8410600b841016171561419c575081810a61086a565b6141a683836140de565b80600019048211156141ba576141ba6140b5565b029392505050565b6000610ac060ff841683614121565b6000602082840312156141e357600080fd5b5051919050565b6000602082840312156141fc57600080fd5b81518015158114610ac057600080fd5b8181038181111561086a5761086a6140b5565b80516dffffffffffffffffffffffffffff8116811461423d57600080fd5b919050565b60008060006060848603121561425757600080fd5b6142608461421f565b925061426e6020850161421f565b9150604084015163ffffffff8116811461428757600080fd5b809150509250925092565b808202811582820484141761086a5761086a6140b5565b600080600080600060a086880312156142c157600080fd5b85516142cc81613e46565b80955050602086015193506040860151925060608601519150608086015161ffff811681146142fa57600080fd5b809150509295509295909350565b634e487b7160e01b600052601260045260246000fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614356816017850160208801613e87565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614393816028840160208801613e87565b01602801949350505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b8181101561441b5784516001600160a01b0316835293830193918301916001016143f6565b50506001600160a01b03969096166060850152505050608001529392505050565b6000602080838503121561444f57600080fd5b825167ffffffffffffffff8082111561446757600080fd5b818501915085601f83011261447b57600080fd5b81518181111561448d5761448d61439f565b8060051b604051601f19603f830116810181811085821117156144b2576144b261439f565b6040529182528482019250838101850191888311156144d057600080fd5b938501935b828510156144ee578451845293850193928501926144d5565b98975050505050505050565b60008060006060848603121561450f57600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052602160045260246000fd5b6000806040838503121561455157600080fd5b505080516020909101519092909150565b600081614571576145716140b5565b506000190190565b6000825161458b818460208701613e87565b919091019291505056fea2646970667358221220529da5378077e1021c658f6431f6dbd55271c7f2a6cfd1f7aebade2d2cb265fb64736f6c63430008110033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106103575760003560e01c806373956bc3116101c8578063a524c99c11610104578063cedb9410116100a2578063dacee3471161007c578063dacee347146107c5578063dd62ed3e146107cd578063e4a3011614610806578063f3fef3a31461081957600080fd5b8063cedb94101461078c578063d505accf1461079f578063d547741f146107b257600080fd5b8063b4eae1cb116100de578063b4eae1cb1461074d578063c00c9f7f14610755578063ca4fb87c1461075d578063cb6290091461078457600080fd5b8063a524c99c1461070a578063a9059cbb1461071d578063b282e0f91461073057600080fd5b80638f839603116101715780639b4dc8cc1161014b5780639b4dc8cc146106bf5780639d938db0146106e6578063a217fddf146106ef578063a457c2d7146106f757600080fd5b80638f8396031461065757806391d148541461067e57806395d89b41146106b757600080fd5b80637a9b71f9116101a25780637a9b71f91461060a5780637ecebe001461061d578063804bbdc61461063057600080fd5b806373956bc3146105a9578063776429e7146105d057806379cc6790146105f757600080fd5b8063313ce5671161029757806342966c68116102405780635b9f00161161021a5780635b9f0016146105495780635da0d90a146105515780636fae2e151461055957806370a082311461058057600080fd5b806342966c681461051a5780635204363e1461052d57806354cf2aeb1461054057600080fd5b806336568abe1161027157806336568abe146104ec57806339509351146104ff578063399c04251461051257600080fd5b8063313ce567146104cd57806335092dad146104dc5780633644e515146104e457600080fd5b8063156e29f61161030457806323b872dd116102de57806323b872dd1461045b578063248a9ca31461046e57806326d71f1e146104915780632f2ff15d146104b857600080fd5b8063156e29f614610433578063158ef93e1461044657806318160ddd1461045357600080fd5b806306fdde031161033557806306fdde03146103e4578063095ea7b3146103f95780630c7c6f011461040c57600080fd5b806301ffc9a71461035c57806302d454571461038457806306d47de9146103c3575b600080fd5b61036f61036a366004613e1c565b61082c565b60405190151581526020015b60405180910390f35b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161037b565b6103d66103d1366004613e5b565b610870565b60405190815260200161037b565b6103ec610980565b60405161037b9190613eab565b61036f610407366004613e5b565b610a12565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6103d6610441366004613ede565b610a2a565b600b5461036f9060ff1681565b6002546103d6565b61036f610469366004613f13565b610aa1565b6103d661047c366004613f54565b60009081526007602052604090206001015490565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6104cb6104c6366004613f6d565b610ac7565b005b6040516006815260200161037b565b6103d6610af1565b6103d6610b00565b6104cb6104fa366004613f6d565b610b0a565b61036f61050d366004613e5b565b610b96565b6103d6610bd5565b6104cb610528366004613f54565b610c05565b6103d661053b366004613ede565b610c12565b6103d6600a5481565b6103d6610ca1565b6103d6610cab565b6103d67f600e5f1c60beb469a3fa6dd3814a4ae211cc6259a6d033bae218a742f2af01d381565b6103d661058e366004613f9d565b6001600160a01b031660009081526020819052604090205490565b6103d67f000000000000000000000000000000000000000000000000000000000000000081565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6104cb610605366004613e5b565b610cb5565b6103d6610618366004613f54565b610cca565b6103d661062b366004613f9d565b610ee2565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6103d67f74a064b2dec4aeb0b53e2d06f8e76ce531a17302a866fe51bc86d9a90b4e85e381565b61036f61068c366004613f6d565b60009182526007602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6103ec610f00565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b6103d660095481565b6103d6600081565b61036f610705366004613e5b565b610f0f565b6103d6610718366004613f54565b610fc4565b61036f61072b366004613e5b565b611040565b61073861104e565b6040805192835260208301919091520161037b565b6103d6611062565b61073861106c565b6103d67f5407862f04286ebe607684514c14b7fffc750b6bf52ba44ea49569174845a5bd81565b6107386112c4565b6103d661079a366004613f54565b6112cf565b6104cb6107ad366004613fba565b6114cd565b6104cb6107c0366004613f6d565b611631565b6103d6611656565b6103d66107db366004614031565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6104cb61081436600461405f565b611677565b6103d6610827366004613e5b565b6119fc565b60006001600160e01b031982167f6ae1097800000000000000000000000000000000000000000000000000000000148061086a575061086a82611b00565b92915050565b60006002600854036108c95760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600855336108e8836108db611b67565b6108e3611c32565b611c3d565b91506108f382611c52565b6109276001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168584611d0e565b6109318184611d9f565b60408051838152602081018590526001600160a01b038316917e3acf01fc7fd0a8bbdc96cfc96b5ddb8fabb57027141a47a3f8ff8c06120517910160405180910390a250600160085592915050565b60606003805461098f90614081565b80601f01602080910402602001604051908101604052809291908181526020018280546109bb90614081565b8015610a085780601f106109dd57610100808354040283529160200191610a08565b820191906000526020600020905b8154815290600101906020018083116109eb57829003601f168201915b5050505050905090565b600033610a20818585611f24565b5060019392505050565b6000600260085403610a7e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108c0565b6002600881905550610a9484848460095461207c565b6001600855949350505050565b600033610aaf8582856121a5565b610aba858585612237565b60019150505b9392505050565b600082815260076020526040902060010154610ae28161244e565b610aec8383612458565b505050565b6000610afb6124fa565b905090565b6000610afb612588565b6001600160a01b0381163314610b885760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084016108c0565b610b9282826126af565b5050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190610a209082908690610bd09087906140cb565b611f24565b6000610afb610be2612732565b610bf9610bf16006600a6141c2565b60095461274b565b6108e36006600a6141c2565b610c0f3382611d9f565b50565b6000600260085403610c665760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108c0565b6002600855610c947f600e5f1c60beb469a3fa6dd3814a4ae211cc6259a6d033bae218a742f2af01d361244e565b610a94848484600061207c565b6000610afb611b67565b6000610afb612757565b610cc08233836121a5565b610b928282611d9f565b60007f00000000000000000000000000000000000000000000000000000000000000008180610cf761278f565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f91906141d1565b90506000610d75610d7085856128ca565b6128d6565b90506000610dde866001600160a01b0316637464fc3d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7091906141d1565b905080821115610e1657610e1383610e0e85610dfa86866128e1565b6108e3610e088860056128ca565b8761274b565b61274b565b92505b50506040516370a0823160e01b81526001600160a01b03851660048201819052600091610e9491906370a0823190602401602060405180830381865afa158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906141d1565b610e0e896108db611b67565b90506000610ea3858385611c3d565b90506000610eb2858486611c3d565b9050610ed582610e0e83610ec689866128e1565b610ed08b886128e1565b6128ed565b9998505050505050505050565b6001600160a01b03811660009081526005602052604081205461086a565b60606004805461098f90614081565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919083811015610fac5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016108c0565b610fb98286868403611f24565b506001949350505050565b6000610fef7f74a064b2dec4aeb0b53e2d06f8e76ce531a17302a866fe51bc86d9a90b4e85e361244e565b5060098054908290557f6f51444e6a490d4270634e3b854e9959ace1fc9b287af8677dfd06d4071f77be33604080516001600160a01b039092168252602082018590520160405180910390a1919050565b600033610a20818585612237565b60008061105961278f565b90939092509050565b6000610afb612732565b6000806110987f5407862f04286ebe607684514c14b7fffc750b6bf52ba44ea49569174845a5bd61244e565b6040517fe2bbb1580000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e2bbb15890604401600060405180830381600087803b15801561113957600080fd5b505af115801561114d573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506370a0823190602401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc91906141d1565b90506111e7816128fa565b506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561124c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127091906141d1565b925061127b83612947565b60408051838152602081018690529081018290529092507fc35d86b8f236816fab54de6cb4b564fc7abbe78e7fa53fc10a3e5ff4b28da8219060600160405180910390a1509091565b600080611059612973565b60007f000000000000000000000000000000000000000000000000000000000000000081806112fc61278f565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611340573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136491906141d1565b905060006113728488612a39565b905060006113818286866128ed565b905061138d858361274b565b945061139984826128e1565b935060006113b16113aa8a856128e1565b8688611c3d565b90508082106113ce576113c489846128e1565b92509050806113df565b60006113db838888611c3d565b9350505b5060006113ef610d7087876128ca565b90506000611434886001600160a01b0316637464fc3d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dba573d6000803e3d6000fd5b9050808211156114535761145085610e0e87610dfa86866128e1565b94505b5050600080611463838688611c3d565b9050600061147285878a611c3d565b905061147e8282612a7a565b9250505060006114a982610bf96006600a61149991906141c2565b6114a4600954612a86565b6128e1565b90506114bf816114b7611c32565b6108e3611b67565b9a9950505050505050505050565b8342111561151d5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e6500000060448201526064016108c0565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861154c8c612b78565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006115a782612b9e565b905060006115b782878787612c07565b9050896001600160a01b0316816001600160a01b03161461161a5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e6174757265000060448201526064016108c0565b6116258a8a8a611f24565b50505050505050505050565b60008281526007602052604090206001015461164c8161244e565b610aec83836126af565b6000610afb6116676006600a6141c2565b61166f611c32565b6108e3612757565b611681600061244e565b600b5460ff16156116d45760405162461bcd60e51b815260206004820152601c60248201527f436f6e747261637420616c726561647920696e697469616c697a65640000000060448201526064016108c0565b600b805460ff191660011790557f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600061176e3390565b90507f00000000000000000000000000000000000000000000000000000000000000006000196117a96001600160a01b03871684308c612c2f565b60405163095ea7b360e01b81526001600160a01b0383811660048301526024820183905288169063095ea7b3906044016020604051808303816000875af11580156117f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181c91906141ea565b5060405163095ea7b360e01b81526001600160a01b0383811660048301526024820183905287169063095ea7b3906044016020604051808303816000875af115801561186c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189091906141ea565b5060405163095ea7b360e01b81526001600160a01b0383811660048301526024820183905286169063095ea7b3906044016020604051808303816000875af11580156118e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190491906141ea565b5060405163095ea7b360e01b81526001600160a01b0383811660048301526024820183905285169063095ea7b3906044016020604051808303816000875af1158015611954573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197891906141ea565b5061198289612947565b5061198b612757565b98506119a7836119a28b8b6108e36006600a6141c2565b612c80565b604080516001600160a01b0385168152602081018b90529081018990527f0f91882b50d9330af0b1d4998e6af7f2eaee90ce7e77ea54fea089af166d021d9060600160405180910390a1505050505050505050565b6000600260085403611a505760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108c0565b6002600855336000611a64846108db611b67565b9050611a6f81612d5f565b9250611aa56001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168685611d0e565b611aaf8285611d9f565b60408051848152602081018690526001600160a01b038416917fdf273cb619d95419a9cd0ec88123a0538c85064229baa6363788f743fff90deb910160405180910390a25050600160085592915050565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061086a57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461086a565b6040517fa23831060000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201523060248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a2383106906044015b602060405180830381865afa158015611c0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610afb91906141d1565b6000610afb60025490565b6000611c4a848484612d83565b949350505050565b6040517f441a3e700000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063441a3e7090604401600060405180830381600087803b158015611cf357600080fd5b505af1158015611d07573d6000803e3d6000fd5b5050505050565b6040516001600160a01b038316602482015260448101829052610aec9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152612e32565b6001600160a01b038216611e1b5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b03821660009081526020819052604090205481811015611eaa5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b0383166000908152602081905260408120838303905560028054849290611ed990849061420c565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6001600160a01b038316611f9f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b03821661201b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000336120b47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316823088612c2f565b60006120be611b67565b905060006120e66120ce88612947565b610bf96120dd6006600a6141c2565b6114a489612a86565b90506120fa816120f4611c32565b84611c3d565b93508584101561214c5760405162461bcd60e51b815260206004820152601860248201527f4d696e696d756d207265717569726564206e6f74206d6574000000000000000060448201526064016108c0565b6121568885612c80565b60408051888152602081018690526001600160a01b038516917f25b428dfde728ccfaddad7e29e4ac23c24ed7fd1a6e3e3f91894a9a073f5dfff910160405180910390a2505050949350505050565b6001600160a01b03838116600090815260016020908152604080832093861683529290522054600019811461223157818110156122245760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016108c0565b6122318484848403611f24565b50505050565b6001600160a01b0383166122b35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b03821661232f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b038316600090815260208190526040902054818110156123be5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906123f59084906140cb565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161244191815260200190565b60405180910390a3612231565b610c0f8133612f17565b60008281526007602090815260408083206001600160a01b038516845290915290205460ff16610b925760008281526007602090815260408083206001600160a01b03851684529091529020805460ff191660011790556124b63390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6040517fe4c75c270000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201523060248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e4c75c2790604401611bf1565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156125e157507f000000000000000000000000000000000000000000000000000000000000000046145b1561260b57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60008281526007602090815260408083206001600160a01b038516845290915290205460ff1615610b925760008281526007602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610afb6127436006600a6141c2565b6108db612757565b6000610ac082846140cb565b600080600061276461278f565b91509150600080612773612973565b9150915061278682610e0e8386886128ed565b94505050505090565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156127f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128179190614242565b50915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161061289c57806dffffffffffffffffffffffffffff16826dffffffffffffffffffffffffffff166128bf565b816dffffffffffffffffffffffffffff16816dffffffffffffffffffffffffffff165b909590945092505050565b6000610ac08284614292565b600061086a82612f97565b6000610ac0828461420c565b6000611c4a8484846130fd565b600061086a7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084613138565b6000806129538361326b565b909350905061296283826132f4565b915061296d82613424565b50919050565b6000806000612980611b67565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a0691906141d1565b9050600080612a1361278f565b91509150612a22848385611c3d565b9550612a2f848285611c3d565b9450505050509091565b6000610ac0612a6b610d70612a61612a54623cda29886128ca565b610e0e623cda20886128ca565b86623cab64611c3d565b6114a4856107cd6107ca611c3d565b6000610ac08383613579565b6040517f1526fe270000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631526fe279060240160a060405180830381865afa158015612b28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4c91906142a9565b9450505050506000612b618261ffff1661358f565b9050611c4a84612b73600a548461274b565b61359c565b6001600160a01b038116600090815260056020526040902080546001810182559061296d565b600061086a612bab612588565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000612c18878787876135a8565b91509150612c2581613695565b5095945050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526122319085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611d53565b6001600160a01b038216612cd65760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016108c0565b8060026000828254612ce891906140cb565b90915550506001600160a01b03821660009081526020819052604081208054839290612d159084906140cb565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600080612d6b83611c52565b612d7483613881565b9092509050610ac082826139aa565b6000808060001985870985870292508281108382030391505080600003612dbd57838281612db357612db3614308565b0492505050610ac0565b808411612dc957600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000612e87826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139b99092919063ffffffff16565b805190915015610aec5780806020019051810190612ea591906141ea565b610aec5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108c0565b60008281526007602090815260408083206001600160a01b038516845290915290205460ff16610b9257612f55816001600160a01b031660146139c8565b612f608360206139c8565b604051602001612f7192919061431e565b60408051601f198184030181529082905262461bcd60e51b82526108c091600401613eab565b600081600003612fa957506000919050565b600182608081901c15612fc15760409190911b9060801c5b604081901c15612fd65760209190911b9060401c5b602081901c15612feb5760109190911b9060201c5b601081901c156130005760089190911b9060101c5b600881901c156130155760049190911b9060081c5b600481901c1561302a5760029190911b9060041c5b600281901c1561303c57600182901b91505b600182858161304d5761304d614308565b048301901c9150600182858161306557613065614308565b048301901c9150600182858161307d5761307d614308565b048301901c9150600182858161309557613095614308565b048301901c915060018285816130ad576130ad614308565b048301901c915060018285816130c5576130c5614308565b048301901c915060018285816130dd576130dd614308565b048301901c9150611c4a828386816130f7576130f7614308565b04613579565b60008061310c856103e5614292565b905061312f818481613120886103e8614292565b61312a91906140cb565b612d83565b95945050505050565b60408051600280825260608201835260009283929190602083019080368337019050509050848482600081518110613172576131726143b5565b602002602001018360018151811061318c5761318c6143b5565b6001600160a01b0393841660209182029290920101529181169091527f0000000000000000000000000000000000000000000000000000000000000000166338ed173984600184306131e0610e10426140cb565b6040518663ffffffff1660e01b81526004016132009594939291906143cb565b6000604051808303816000875af115801561321f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613247919081019061443c565b600181518110613259576132596143b5565b60200260200101519150509392505050565b600080600061327861278f565b50905060006132878286612a39565b9050806132d65760405162461bcd60e51b815260206004820152600f60248201527f4e6f7468696e6720746f2073776170000000000000000000000000000000000060448201526064016108c0565b6132df81613bf1565b92506132eb85826128e1565b93505050915091565b6000806001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e8e337007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000087876001803061337a610e10426140cb565b60405160e08a901b6001600160e01b03191681526001600160a01b039889166004820152968816602488015260448701959095526064860193909352608485019190915260a484015290921660c482015260e4810191909152610104016060604051808303816000875af11580156133f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061341a91906144fa565b9695505050505050565b60405163095ea7b360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000818116600484015260248301849052917f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af11580156134b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134db91906141ea565b506040517fe2bbb1580000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152602481018390526001600160a01b0382169063e2bbb15890604401600060405180830381600087803b15801561355d57600080fd5b505af1158015613571573d6000803e3d6000fd5b505050505050565b60008183106135885781610ac0565b5090919050565b600061086a826064614292565b6000610ac08383613c3e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156135df575060009050600361368c565b8460ff16601b141580156135f757508460ff16601c14155b15613608575060009050600461368c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561365c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166136855760006001925092505061368c565b9150600090505b94509492505050565b60008160048111156136a9576136a9614528565b036136b15750565b60018160048111156136c5576136c5614528565b036137125760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108c0565b600281600481111561372657613726614528565b036137735760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108c0565b600381600481111561378757613787614528565b036137fa5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b600481600481111561380e5761380e614528565b03610c0f5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016108c0565b60008080806001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663baa2abde7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008860018030613908610e10426140cb565b60405160e089901b6001600160e01b03191681526001600160a01b039788166004820152958716602487015260448601949094526064850192909252608484015290921660a482015260c481019190915260e40160408051808303816000875af115801561397a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061399e919061453e565b90969095509350505050565b6000610ac083610e0e84613c4e565b6060611c4a8484600085613c9b565b606060006139d7836002614292565b6139e29060026140cb565b67ffffffffffffffff8111156139fa576139fa61439f565b6040519080825280601f01601f191660200182016040528015613a24576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613a5b57613a5b6143b5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613abe57613abe6143b5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000613afa846002614292565b613b059060016140cb565b90505b6001811115613ba2577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613b4657613b466143b5565b1a60f81b828281518110613b5c57613b5c6143b5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93613b9b81614562565b9050613b08565b508315610ac05760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108c0565b600061086a7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084613138565b6000818310156135885781610ac0565b600061086a7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084613138565b606082471015613d135760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016108c0565b6001600160a01b0385163b613d6a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108c0565b600080866001600160a01b03168587604051613d869190614579565b60006040518083038185875af1925050503d8060008114613dc3576040519150601f19603f3d011682016040523d82523d6000602084013e613dc8565b606091505b5091509150613dd8828286613de3565b979650505050505050565b60608315613df2575081610ac0565b825115613e025782518084602001fd5b8160405162461bcd60e51b81526004016108c09190613eab565b600060208284031215613e2e57600080fd5b81356001600160e01b031981168114610ac057600080fd5b6001600160a01b0381168114610c0f57600080fd5b60008060408385031215613e6e57600080fd5b8235613e7981613e46565b946020939093013593505050565b60005b83811015613ea2578181015183820152602001613e8a565b50506000910152565b6020815260008251806020840152613eca816040850160208701613e87565b601f01601f19169190910160400192915050565b600080600060608486031215613ef357600080fd5b8335613efe81613e46565b95602085013595506040909401359392505050565b600080600060608486031215613f2857600080fd5b8335613f3381613e46565b92506020840135613f4381613e46565b929592945050506040919091013590565b600060208284031215613f6657600080fd5b5035919050565b60008060408385031215613f8057600080fd5b823591506020830135613f9281613e46565b809150509250929050565b600060208284031215613faf57600080fd5b8135610ac081613e46565b600080600080600080600060e0888a031215613fd557600080fd5b8735613fe081613e46565b96506020880135613ff081613e46565b95506040880135945060608801359350608088013560ff8116811461401457600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561404457600080fd5b823561404f81613e46565b91506020830135613f9281613e46565b6000806040838503121561407257600080fd5b50508035926020909101359150565b600181811c9082168061409557607f821691505b60208210810361296d57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561086a5761086a6140b5565b600181815b808511156141195781600019048211156140ff576140ff6140b5565b8085161561410c57918102915b93841c93908002906140e3565b509250929050565b6000826141305750600161086a565b8161413d5750600061086a565b8160018114614153576002811461415d57614179565b600191505061086a565b60ff84111561416e5761416e6140b5565b50506001821b61086a565b5060208310610133831016604e8410600b841016171561419c575081810a61086a565b6141a683836140de565b80600019048211156141ba576141ba6140b5565b029392505050565b6000610ac060ff841683614121565b6000602082840312156141e357600080fd5b5051919050565b6000602082840312156141fc57600080fd5b81518015158114610ac057600080fd5b8181038181111561086a5761086a6140b5565b80516dffffffffffffffffffffffffffff8116811461423d57600080fd5b919050565b60008060006060848603121561425757600080fd5b6142608461421f565b925061426e6020850161421f565b9150604084015163ffffffff8116811461428757600080fd5b809150509250925092565b808202811582820484141761086a5761086a6140b5565b600080600080600060a086880312156142c157600080fd5b85516142cc81613e46565b80955050602086015193506040860151925060608601519150608086015161ffff811681146142fa57600080fd5b809150509295509295909350565b634e487b7160e01b600052601260045260246000fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614356816017850160208801613e87565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614393816028840160208801613e87565b01602801949350505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b8181101561441b5784516001600160a01b0316835293830193918301916001016143f6565b50506001600160a01b03969096166060850152505050608001529392505050565b6000602080838503121561444f57600080fd5b825167ffffffffffffffff8082111561446757600080fd5b818501915085601f83011261447b57600080fd5b81518181111561448d5761448d61439f565b8060051b604051601f19603f830116810181811085821117156144b2576144b261439f565b6040529182528482019250838101850191888311156144d057600080fd5b938501935b828510156144ee578451845293850193928501926144d5565b98975050505050505050565b60008060006060848603121561450f57600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052602160045260246000fd5b6000806040838503121561455157600080fd5b505080516020909101519092909150565b600081614571576145716140b5565b506000190190565b6000825161458b818460208701613e87565b919091019291505056fea2646970667358221220529da5378077e1021c658f6431f6dbd55271c7f2a6cfd1f7aebade2d2cb265fb64736f6c63430008110033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "DOMAIN_SEPARATOR()": {
        "details": "See {IERC20Permit-DOMAIN_SEPARATOR}."
      },
      "allowance(address,address)": {
        "details": "See {IERC20-allowance}."
      },
      "approve(address,uint256)": {
        "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address."
      },
      "balanceOf(address)": {
        "details": "See {IERC20-balanceOf}."
      },
      "burn(uint256)": {
        "details": "Destroys `amount` tokens from the caller. See {ERC20-_burn}."
      },
      "burnFrom(address,uint256)": {
        "details": "Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`."
      },
      "buyingPrice()": {
        "returns": {
          "price": " Minting price in USDC tokens per PE token"
        }
      },
      "collateralRatio()": {
        "returns": {
          "ratio": " Ratio of USDC tokens per PE token, with `_decimal` decimals"
        }
      },
      "compoundRewards()": {
        "custom:emit": "CompoundRewards",
        "returns": {
          "lpAmount": " The number of LP USDC/MAI tokens being put on stake",
          "usdcAmount": " The number of USDC tokens being re-invested"
        }
      },
      "constructor": {
        "params": {
          "_lpAddress": "LP Address for MAI/USDC",
          "_maiAddress": "Address used for the MAI tokens in vault",
          "_qiAddress": "Address used for the QI tokens in vault",
          "_qiDaoFarmAddress": "Address of the QiDao Farm to use",
          "_qiDaoPoolId": "Pool ID within the QiDao Farm",
          "_quickSwapRouterAddress": "Address of the QuickSwap Router to talk to",
          "_usdcAddress": "Address used for the USDC tokens in vault"
        }
      },
      "decimals()": {
        "returns": {
          "decimals_": " This will always be 6"
        }
      },
      "decreaseAllowance(address,uint256)": {
        "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`."
      },
      "getLpReserves()": {
        "returns": {
          "maiReserves": " Number of MAI tokens in reserve",
          "usdcReserves": " Number of USDC tokens in reserve"
        }
      },
      "getPendingRewardsAmount()": {
        "returns": {
          "qiAmount": " Number of QI tokens accrued"
        }
      },
      "getRoleAdmin(bytes32)": {
        "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."
      },
      "grantRole(bytes32,address)": {
        "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."
      },
      "hasRole(bytes32,address)": {
        "details": "Returns `true` if `account` has been granted `role`."
      },
      "increaseAllowance(address,uint256)": {
        "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address."
      },
      "initialize(uint256,uint256)": {
        "custom:emit": "Initialized",
        "params": {
          "startingRatio": "Initial minting ratio in PE tokens per USDC tokens minted (including DECIMALS)",
          "usdcAmount": "Number of collateral USDC tokens"
        }
      },
      "mint(address,uint256,uint256)": {
        "custom:emit": "Minted",
        "params": {
          "minReceive": "The minimum number of PE tokens to mint",
          "to": "The address to transfer the minted PE tokens to",
          "usdcAmount": "Number of USDC tokens to use as collateral"
        },
        "returns": {
          "peAmount": " The number of PE tokens actually minted"
        }
      },
      "mintForMigration(address,uint256,uint256)": {
        "custom:emit": "Minted",
        "params": {
          "minReceive": "The minimum number of PE tokens to mint",
          "to": "The address to transfer the minted PE tokens to",
          "usdcAmount": "Number of USDC tokens to use as collateral"
        },
        "returns": {
          "peAmount": " The number of PE tokens actually minted"
        }
      },
      "name()": {
        "details": "Returns the name of the token."
      },
      "nonces(address)": {
        "details": "See {IERC20Permit-nonces}."
      },
      "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": {
        "details": "See {IERC20Permit-permit}."
      },
      "quoteIn(uint256)": {
        "details": "This method was obtained by _inlining_ the call to mint() across contracts, and cleaning up the result.",
        "params": {
          "usdc": "Number of USDC tokens to quote for"
        },
        "returns": {
          "pe": " Number of PE tokens quoted for the given number of USDC tokens"
        }
      },
      "quoteOut(uint256)": {
        "details": "This method was obtained by _inlining_ the call to withdraw() across contracts, and cleaning up the result.",
        "params": {
          "pe": "Number of PE tokens to quote for"
        },
        "returns": {
          "usdc": " Number of USDC tokens quoted for the given number of PE tokens"
        }
      },
      "renounceRole(bytes32,address)": {
        "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`. May emit a {RoleRevoked} event."
      },
      "revokeRole(bytes32,address)": {
        "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."
      },
      "setMarkupFee(uint256)": {
        "custom:emit": "MarkupFeeUpdated",
        "params": {
          "newMarkupFee": "New markup fee value"
        },
        "returns": {
          "prevMarkupFee": " Previous markup fee value"
        }
      },
      "stakedBalance()": {
        "returns": {
          "lpAmount": " Number of LP USDC/MAI token on stake"
        }
      },
      "stakedTokens()": {
        "returns": {
          "maiAmount": " Number of MAI tokens on stake",
          "usdcAmount": " Number of USDC tokens on stake"
        }
      },
      "stakedValue()": {
        "returns": {
          "usdcAmount": " Total equivalent number of USDC token on stake"
        }
      },
      "supportsInterface(bytes4)": {
        "params": {
          "interfaceId": "Interface ID to check against"
        },
        "returns": {
          "_0": "Whether the provided interface ID is supported"
        }
      },
      "symbol()": {
        "details": "Returns the symbol of the token, usually a shorter version of the name."
      },
      "totalSupply()": {
        "details": "See {IERC20-totalSupply}."
      },
      "transfer(address,uint256)": {
        "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`."
      },
      "transferFrom(address,address,uint256)": {
        "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`."
      },
      "usdcPrice()": {
        "returns": {
          "price": " Collateralized price in USDC tokens per PE token"
        }
      },
      "withdraw(address,uint256)": {
        "custom:emit": "Withdrawal",
        "params": {
          "peAmount": "Number of PE tokens to withdraw",
          "to": "Address to deposit extracted USDC tokens into"
        },
        "returns": {
          "usdcTotal": " Number of USDC tokens extracted"
        }
      },
      "withdrawLiquidity(address,uint256)": {
        "custom:emit": "LiquidityWithdrawal",
        "params": {
          "peAmount": "Number of PE tokens to withdraw liquidity for",
          "to": "Address to deposit extracted LP USDC/MAI tokens into"
        },
        "returns": {
          "lpAmount": " Number of LP USDC/MAI tokens extracted"
        }
      }
    },
    "stateVariables": {
      "MARKUP_ROLE": {
        "return": " The role hash in question",
        "returns": {
          "_0": " The role hash in question"
        }
      },
      "MIGRATOR_ROLE": {
        "return": " The role hash in question",
        "returns": {
          "_0": " The role hash in question"
        }
      },
      "REWARDS_ROLE": {
        "return": " The role hash in question",
        "returns": {
          "_0": " The role hash in question"
        }
      },
      "initialized": {
        "return": "True whenever the contract has already been initialized, false otherwise",
        "returns": {
          "_0": "True whenever the contract has already been initialized, false otherwise"
        }
      },
      "lpAddress": {
        "return": "The address in question",
        "returns": {
          "_0": "The address in question"
        }
      },
      "maiAddress": {
        "return": "The address in question",
        "returns": {
          "_0": "The address in question"
        }
      },
      "markupFee": {
        "return": "The markup fee to use",
        "returns": {
          "_0": "The markup fee to use"
        }
      },
      "qiAddress": {
        "return": "The address in question",
        "returns": {
          "_0": "The address in question"
        }
      },
      "qiDaoFarmAddress": {
        "return": "The address in question",
        "returns": {
          "_0": "The address in question"
        }
      },
      "qiDaoPoolId": {
        "return": "The pool ID in question",
        "returns": {
          "_0": "The pool ID in question"
        }
      },
      "quickSwapRouterAddress": {
        "return": "The address in question",
        "returns": {
          "_0": "The address in question"
        }
      },
      "swapFee": {
        "return": "The swap fee to use",
        "returns": {
          "_0": "The swap fee to use"
        }
      },
      "usdcAddress": {
        "return": "The address in question",
        "returns": {
          "_0": "The address in question"
        }
      }
    },
    "version": 1
  },
  "userdoc": {
    "events": {
      "CompoundRewards(uint256,uint256,uint256)": {
        "notice": "Emitted upon compounding rewards from QiDao's Farm back into the vault"
      },
      "Initialized(address,uint256,uint256)": {
        "notice": "Emitted upon initialization of the Peronio contract"
      },
      "LiquidityWithdrawal(address,uint256,uint256)": {
        "notice": "Emitted upon liquidity withdrawal"
      },
      "MarkupFeeUpdated(address,uint256)": {
        "notice": "Emitted upon the markup fee being updated"
      },
      "Minted(address,uint256,uint256)": {
        "notice": "Emitted upon minting PE tokens"
      },
      "Withdrawal(address,uint256,uint256)": {
        "notice": "Emitted upon collateral withdrawal"
      }
    },
    "kind": "user",
    "methods": {
      "MARKUP_ROLE()": {
        "notice": "Return the hash identifying the role responsible for updating the markup fee"
      },
      "MIGRATOR_ROLE()": {
        "notice": "Return the hash identifying the role responsible for migrating between versions"
      },
      "REWARDS_ROLE()": {
        "notice": "Return the hash identifying the role responsible for compounding rewards"
      },
      "buyingPrice()": {
        "notice": "Return the effective _minting_ price in USDC tokens per PE token"
      },
      "collateralRatio()": {
        "notice": "Return the ratio of total number of USDC tokens per PE token"
      },
      "compoundRewards()": {
        "notice": "Claim QiDao's QI token rewards, and re-invest them in the QuickSwap liquidity pool and QiDao's Farm"
      },
      "constructor": {
        "notice": "Construct a new Peronio contract"
      },
      "decimals()": {
        "notice": "Return the number of decimals the PE token will work with"
      },
      "getLpReserves()": {
        "notice": "Return the USDC and MAI token reserves present in QuickSwap"
      },
      "getPendingRewardsAmount()": {
        "notice": "Return the rewards accrued by staking LP USDC/MAI tokens in QiDao's Farm (in QI tokens)"
      },
      "initialize(uint256,uint256)": {
        "notice": "Initialize the PE token by providing collateral USDC tokens - initial conversion rate will be set at the given starting ratio"
      },
      "initialized()": {
        "notice": "Return wether the Peronio contract has been initialized yet"
      },
      "lpAddress()": {
        "notice": "Return the address used for the LP USDC/MAI tokens in vault"
      },
      "maiAddress()": {
        "notice": "Return the address used for the MAI tokens in vault"
      },
      "markupFee()": {
        "notice": "Return the markup fee the use, using `_decimals()` decimals implicitly"
      },
      "mint(address,uint256,uint256)": {
        "notice": "Mint PE tokens using the provided USDC tokens as collateral"
      },
      "mintForMigration(address,uint256,uint256)": {
        "notice": "Mint PE tokens using the provided USDC tokens as collateral --- used by the migrators in order not to incur normal fees"
      },
      "qiAddress()": {
        "notice": "Return the address used for the QI tokens in vault"
      },
      "qiDaoFarmAddress()": {
        "notice": "Return the address of the QiDao Farm to use"
      },
      "qiDaoPoolId()": {
        "notice": "Return the pool ID within the QiDao Farm"
      },
      "quickSwapRouterAddress()": {
        "notice": "Return the address of the QuickSwap Router to talk to"
      },
      "quoteIn(uint256)": {
        "notice": "Retrieve the expected number of PE tokens corresponding to the given number of USDC tokens for minting."
      },
      "quoteOut(uint256)": {
        "notice": "Retrieve the expected number of USDC tokens corresponding to the given number of PE tokens for withdrawal."
      },
      "setMarkupFee(uint256)": {
        "notice": "Set the markup fee to the given value (take into account that this will use `DECIMALS` decimals implicitly)"
      },
      "stakedBalance()": {
        "notice": "Return the number of LP USDC/MAI tokens on stake at QiDao's Farm"
      },
      "stakedTokens()": {
        "notice": "Return the number of USDC and MAI tokens on stake at QiDao's Farm"
      },
      "stakedValue()": {
        "notice": "Return the equivalent number of USDC tokens on stake at QiDao's Farm"
      },
      "supportsInterface(bytes4)": {
        "notice": "Implementation of the IERC165 interface"
      },
      "swapFee()": {
        "notice": "Return the swap fee the use, using `_decimals()` decimals implicitly"
      },
      "usdcAddress()": {
        "notice": "Return the address used for the USDC tokens in vault"
      },
      "usdcPrice()": {
        "notice": "Return the _collateralized_ price in USDC tokens per PE token"
      },
      "withdraw(address,uint256)": {
        "notice": "Extract the given number of PE tokens as USDC tokens"
      },
      "withdrawLiquidity(address,uint256)": {
        "notice": "Extract the given number of PE tokens as LP USDC/MAI tokens"
      }
    },
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 484,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_balances",
        "offset": 0,
        "slot": "0",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 490,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_allowances",
        "offset": 0,
        "slot": "1",
        "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))"
      },
      {
        "astId": 492,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_totalSupply",
        "offset": 0,
        "slot": "2",
        "type": "t_uint256"
      },
      {
        "astId": 494,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_name",
        "offset": 0,
        "slot": "3",
        "type": "t_string_storage"
      },
      {
        "astId": 496,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_symbol",
        "offset": 0,
        "slot": "4",
        "type": "t_string_storage"
      },
      {
        "astId": 1224,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_nonces",
        "offset": 0,
        "slot": "5",
        "type": "t_mapping(t_address,t_struct(Counter)2013_storage)"
      },
      {
        "astId": 1232,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_PERMIT_TYPEHASH_DEPRECATED_SLOT",
        "offset": 0,
        "slot": "6",
        "type": "t_bytes32"
      },
      {
        "astId": 60,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_roles",
        "offset": 0,
        "slot": "7",
        "type": "t_mapping(t_bytes32,t_struct(RoleData)55_storage)"
      },
      {
        "astId": 439,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "_status",
        "offset": 0,
        "slot": "8",
        "type": "t_uint256"
      },
      {
        "astId": 11916,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "markupFee",
        "offset": 0,
        "slot": "9",
        "type": "t_userDefinedValueType(RatioWith6Decimals)3426"
      },
      {
        "astId": 11924,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "swapFee",
        "offset": 0,
        "slot": "10",
        "type": "t_userDefinedValueType(RatioWith6Decimals)3426"
      },
      {
        "astId": 11927,
        "contract": "contracts/Peronio.sol:Peronio",
        "label": "initialized",
        "offset": 0,
        "slot": "11",
        "type": "t_bool"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_bytes32": {
        "encoding": "inplace",
        "label": "bytes32",
        "numberOfBytes": "32"
      },
      "t_mapping(t_address,t_bool)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => bool)",
        "numberOfBytes": "32",
        "value": "t_bool"
      },
      "t_mapping(t_address,t_mapping(t_address,t_uint256))": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => mapping(address => uint256))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_address,t_uint256)"
      },
      "t_mapping(t_address,t_struct(Counter)2013_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct Counters.Counter)",
        "numberOfBytes": "32",
        "value": "t_struct(Counter)2013_storage"
      },
      "t_mapping(t_address,t_uint256)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_mapping(t_bytes32,t_struct(RoleData)55_storage)": {
        "encoding": "mapping",
        "key": "t_bytes32",
        "label": "mapping(bytes32 => struct AccessControl.RoleData)",
        "numberOfBytes": "32",
        "value": "t_struct(RoleData)55_storage"
      },
      "t_string_storage": {
        "encoding": "bytes",
        "label": "string",
        "numberOfBytes": "32"
      },
      "t_struct(Counter)2013_storage": {
        "encoding": "inplace",
        "label": "struct Counters.Counter",
        "members": [
          {
            "astId": 2012,
            "contract": "contracts/Peronio.sol:Peronio",
            "label": "_value",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          }
        ],
        "numberOfBytes": "32"
      },
      "t_struct(RoleData)55_storage": {
        "encoding": "inplace",
        "label": "struct AccessControl.RoleData",
        "members": [
          {
            "astId": 52,
            "contract": "contracts/Peronio.sol:Peronio",
            "label": "members",
            "offset": 0,
            "slot": "0",
            "type": "t_mapping(t_address,t_bool)"
          },
          {
            "astId": 54,
            "contract": "contracts/Peronio.sol:Peronio",
            "label": "adminRole",
            "offset": 0,
            "slot": "1",
            "type": "t_bytes32"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      },
      "t_userDefinedValueType(RatioWith6Decimals)3426": {
        "encoding": "inplace",
        "label": "RatioWith6Decimals",
        "numberOfBytes": "32"
      }
    }
  }
}