From 224da037cfc213101d97c8d9129d544300ac70f6 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 14 Jun 2022 17:15:46 -0700 Subject: [PATCH 01/82] add controller helper abi and atoms --- .../frontend/src/abis/controllerHelper.json | 891 ++++++++++++++++++ packages/frontend/src/constants/address.ts | 7 + .../frontend/src/state/positions/atoms.ts | 2 + 3 files changed, 900 insertions(+) create mode 100644 packages/frontend/src/abis/controllerHelper.json diff --git a/packages/frontend/src/abis/controllerHelper.json b/packages/frontend/src/abis/controllerHelper.json new file mode 100644 index 000000000..a007d7943 --- /dev/null +++ b/packages/frontend/src/abis/controllerHelper.json @@ -0,0 +1,891 @@ +{ + "address": "0xfa86d43b41Fa7a759c606130cc81970A955ff816", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "address", + "name": "_nonfungiblePositionManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_uniswapFactory", + "type": "address" + }, + { + "internalType": "address", + "name": "_exec", + "type": "address" + }, + { + "internalType": "address", + "name": "_euler", + "type": "address" + }, + { + "internalType": "address", + "name": "_dToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidityPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToWithdraw", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limitPriceEthPerPowerPerp", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0Min", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Min", + "type": "uint128" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + }, + { + "internalType": "bool", + "name": "burnExactRemoved", + "type": "bool" + } + ], + "internalType": "struct ControllerHelperDataType.CloseShortWithUserNftParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "closeShortWithUserNft", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "dToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "euler", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "exec", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidityPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToFlashloan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToWithdraw", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limitPriceEthPerPowerPerp", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0Min", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Min", + "type": "uint128" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + }, + { + "internalType": "bool", + "name": "burnExactRemoved", + "type": "bool" + } + ], + "internalType": "struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam", + "name": "_params", + "type": "tuple" + } + ], + "name": "flashloanCloseVaultLpNft", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "wPowerPerpPool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToFlashloan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToLp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToWithdraw", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "lowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "upperTick", + "type": "int24" + } + ], + "internalType": "struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "flashloanWMintLpDepositNft", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToMint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToSell", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minToReceive", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + } + ], + "internalType": "struct ControllerHelperDataType.FlashSellLongWMintParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "flashswapSellLongWMint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToBuy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToWithdraw", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxToPay", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + } + ], + "internalType": "struct ControllerHelperDataType.FlashswapWBurnBuyLongParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "flashswapWBurnBuyLong", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedData", + "type": "bytes" + } + ], + "name": "onDeferredLiquidityCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_collateralToFlashloan", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "enum ControllerHelperDataType.RebalanceVaultNftType", + "name": "rebalanceLpInVaultType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct ControllerHelperDataType.RebalanceLpInVaultParams[]", + "name": "_params", + "type": "tuple[]" + } + ], + "name": "rebalanceLpInVault", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "wPowerPerpPool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wethAmountDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0DesiredMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1DesiredMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limitPriceEthPerPowerPerp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "lowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "upperTick", + "type": "int24" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + } + ], + "internalType": "struct ControllerHelperDataType.RebalanceLpWithoutVaultParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "rebalanceLpWithoutVault", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidityPercentage", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0Min", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Min", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "limitPriceEthPerPowerPerp", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + } + ], + "internalType": "struct ControllerHelperDataType.ReduceLiquidityAndSellParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "reduceLiquidityAndSell", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "wPowerPerpPool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToLp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "lowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "upperTick", + "type": "int24" + } + ], + "internalType": "struct ControllerHelperDataType.MintAndLpParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "wMintLp", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", + "receipt": { + "to": null, + "from": "0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA", + "contractAddress": "0xfa86d43b41Fa7a759c606130cc81970A955ff816", + "transactionIndex": 166, + "gasUsed": "5438748", + "logsBloom": "0x00800000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000002010000080000000000000000200000000000000000800000000000400000000000000000000000000008000000000002000000000004100001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000200000000000000000000040002000000000020000000000000000000000000000000000000000020000000010200800000000000000000000000800000000000000000000000000000000", + "blockHash": "0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6", + "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", + "logs": [ + { + "transactionIndex": 166, + "blockNumber": 14925294, + "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", + "address": "0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816", + "0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 237, + "blockHash": "0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6" + }, + { + "transactionIndex": 166, + "blockNumber": 14925294, + "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", + "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816", + "0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 238, + "blockHash": "0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6" + }, + { + "transactionIndex": 166, + "blockNumber": 14925294, + "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", + "address": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88", + "topics": [ + "0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31", + "0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816", + "0x00000000000000000000000064187ae08781b09368e6253f9e94951243a493d5" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 239, + "blockHash": "0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6" + } + ], + "blockNumber": 14925294, + "cumulativeGasUsed": "17334095", + "status": 1, + "byzantium": true + }, + "args": [ + "0x64187ae08781B09368e6253F9E94951243A493D5", + "0xC36442b4a4522E871399CD717aBDD847Ab11FE88", + "0x1F98431c8aD98523631AE4a59f267346ea31F984", + "0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80", + "0x27182842E098f60e3D576794A5bFFb0777E025d3", + "0x62e28f054efc24b26A794F5C1249B6349454352C" + ], + "solcInputHash": "fc32ed9e00a9017e491333926bef5473", + "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_controller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_nonfungiblePositionManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_uniswapFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_exec\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_euler\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityPercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToBurn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToWithdraw\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limitPriceEthPerPowerPerp\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"amount0Min\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Min\",\"type\":\"uint128\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"},{\"internalType\":\"bool\",\"name\":\"burnExactRemoved\",\"type\":\"bool\"}],\"internalType\":\"struct ControllerHelperDataType.CloseShortWithUserNftParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"closeShortWithUserNft\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"euler\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exec\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityPercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToBurn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToFlashloan\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToWithdraw\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limitPriceEthPerPowerPerp\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"amount0Min\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Min\",\"type\":\"uint128\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"},{\"internalType\":\"bool\",\"name\":\"burnExactRemoved\",\"type\":\"bool\"}],\"internalType\":\"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"flashloanCloseVaultLpNft\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"wPowerPerpPool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToDeposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToFlashloan\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToLp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToWithdraw\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0Min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Min\",\"type\":\"uint256\"},{\"internalType\":\"int24\",\"name\":\"lowerTick\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"upperTick\",\"type\":\"int24\"}],\"internalType\":\"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"flashloanWMintLpDepositNft\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToMint\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToDeposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToSell\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToReceive\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"}],\"internalType\":\"struct ControllerHelperDataType.FlashSellLongWMintParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"flashswapSellLongWMint\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToBurn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToBuy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToWithdraw\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxToPay\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"}],\"internalType\":\"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"flashswapWBurnBuyLong\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedData\",\"type\":\"bytes\"}],\"name\":\"onDeferredLiquidityCheck\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_collateralToFlashloan\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"enum ControllerHelperDataType.RebalanceVaultNftType\",\"name\":\"rebalanceLpInVaultType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\",\"name\":\"_params\",\"type\":\"tuple[]\"}],\"name\":\"rebalanceLpInVault\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"wPowerPerpPool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wethAmountDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0DesiredMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1DesiredMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limitPriceEthPerPowerPerp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0Min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Min\",\"type\":\"uint256\"},{\"internalType\":\"int24\",\"name\":\"lowerTick\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"upperTick\",\"type\":\"int24\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"}],\"internalType\":\"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"rebalanceLpWithoutVault\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityPercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"amount0Min\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Min\",\"type\":\"uint128\"},{\"internalType\":\"uint256\",\"name\":\"limitPriceEthPerPowerPerp\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"}],\"internalType\":\"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"reduceLiquidityAndSell\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"wPowerPerpPool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToDeposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToLp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0Min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Min\",\"type\":\"uint256\"},{\"internalType\":\"int24\",\"name\":\"lowerTick\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"upperTick\",\"type\":\"int24\"}],\"internalType\":\"struct ControllerHelperDataType.MintAndLpParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"wMintLp\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\":{\"details\":\"user should approve this contract for Uni NFT transfer\",\"params\":{\"_params\":\"ControllerHelperDataType.CloseShortWithUserNftParams struct\"}},\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\":{\"details\":\"sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\",\"params\":{\"_params\":\"ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\"}},\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\":{\"details\":\"flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\",\"params\":{\"_params\":\"ControllerHelperDataType.FlashSellLongWMintParams struct\"}},\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\":{\"details\":\"this function\",\"params\":{\"_params\":\"ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\"}},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"accept erc721 from safeTransferFrom and safeMint after callback\",\"returns\":{\"_0\":\"returns received selector\"}},\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\":{\"params\":{\"_collateralToFlashloan\":\"collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\",\"_params\":\"array of ControllerHelperDataType.RebalanceLpInVaultParams structs\",\"_vaultId\":\"vault ID\"}},\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\":{\"params\":{\"_params\":\"ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\"}},\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\":{\"params\":{\"_params\":\"ControllerHelperDataType.ReduceLiquidityAndSellParams struct\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"params\":{\"_data\":\"callback data encoded as SwapCallbackData struct\",\"amount0Delta\":\"amount of token0\",\"amount1Delta\":\"amount of token1\"}},\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\":{\"params\":{\"_params\":\"ControllerHelperDataType.MintAndLpParams struct\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\":{\"notice\":\"close short position with user Uniswap v3 LP NFT\"},\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\":{\"notice\":\"FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\"},\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\":{\"notice\":\"sell long wPowerPerp and flashswap mint short position\"},\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\":{\"notice\":\"flash close position and buy long squeeth\"},\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\":{\"notice\":\"Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\"},\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\":{\"notice\":\"Rebalance LP nft through trading\"},\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\":{\"notice\":\"sell all LP wPowerPerp amounts to WETH and send back to user\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"uniswap swap callback function for flashswap\"},\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\":{\"notice\":\"mint WPowerPerp and LP into Uniswap v3 pool\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/periphery/ControllerHelper.sol\":\"ControllerHelper\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\":\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, 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 `sender` to `recipient` 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(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n */\\n function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\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 function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 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 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\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(address target, bytes memory data, string memory errorMessage) 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(address target, bytes memory data, uint256 value) 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(address target, bytes memory data, uint256 value, string memory errorMessage) 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 // solhint-disable-next-line avoid-low-level-calls\\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(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\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(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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\\n // solhint-disable-next-line no-inline-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\":\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\",\"license\":\"MIT\"},\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n IUniswapV3PoolImmutables,\\n IUniswapV3PoolState,\\n IUniswapV3PoolDerivedState,\\n IUniswapV3PoolActions,\\n IUniswapV3PoolOwnerActions,\\n IUniswapV3PoolEvents\\n{\\n\\n}\\n\",\"keccak256\":\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n function uniswapV3FlashCallback(\\n uint256 fee0,\\n uint256 fee1,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x151ba1777392771025f0fca946c95fbc16ec4b5eff05e1f236115b99bd574de2\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#swap\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\ninterface IUniswapV3SwapCallback {\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissionless pool actions\\n/// @notice Contains pool methods that can be called by anyone\\ninterface IUniswapV3PoolActions {\\n /// @notice Sets the initial price for the pool\\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\n function initialize(uint160 sqrtPriceX96) external;\\n\\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\n /// @param recipient The address for which the liquidity will be created\\n /// @param tickLower The lower tick of the position in which to add liquidity\\n /// @param tickUpper The upper tick of the position in which to add liquidity\\n /// @param amount The amount of liquidity to mint\\n /// @param data Any data that should be passed through to the callback\\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n function mint(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount,\\n bytes calldata data\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Collects tokens owed to a position\\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\n /// @param recipient The address which should receive the fees collected\\n /// @param tickLower The lower tick of the position for which to collect fees\\n /// @param tickUpper The upper tick of the position for which to collect fees\\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\n /// @return amount0 The amount of fees collected in token0\\n /// @return amount1 The amount of fees collected in token1\\n function collect(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n\\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\n /// @dev Fees must be collected separately via a call to #collect\\n /// @param tickLower The lower tick of the position for which to burn liquidity\\n /// @param tickUpper The upper tick of the position for which to burn liquidity\\n /// @param amount How much liquidity to burn\\n /// @return amount0 The amount of token0 sent to the recipient\\n /// @return amount1 The amount of token1 sent to the recipient\\n function burn(\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Swap token0 for token1, or token1 for token0\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\n /// @param recipient The address to receive the output of the swap\\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\n /// @param data Any data to be passed through to the callback\\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n\\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\n /// @param recipient The address which will receive the token0 and token1 amounts\\n /// @param amount0 The amount of token0 to send\\n /// @param amount1 The amount of token1 to send\\n /// @param data Any data to be passed through to the callback\\n function flash(\\n address recipient,\\n uint256 amount0,\\n uint256 amount1,\\n bytes calldata data\\n ) external;\\n\\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\n /// the input observationCardinalityNext.\\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\n function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\n}\\n\",\"keccak256\":\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that is not stored\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\n/// blockchain. The functions here may have variable gas costs.\\ninterface IUniswapV3PoolDerivedState {\\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\n /// you must call it with secondsAgos = [3600, 0].\\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\n /// timestamp\\n function observe(uint32[] calldata secondsAgos)\\n external\\n view\\n returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\n\\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\n /// snapshot is taken and the second snapshot is taken.\\n /// @param tickLower The lower tick of the range\\n /// @param tickUpper The upper tick of the range\\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\n /// @return secondsInside The snapshot of seconds per liquidity for the range\\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (\\n int56 tickCumulativeInside,\\n uint160 secondsPerLiquidityInsideX128,\\n uint32 secondsInside\\n );\\n}\\n\",\"keccak256\":\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Events emitted by a pool\\n/// @notice Contains all events emitted by the pool\\ninterface IUniswapV3PoolEvents {\\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\n event Initialize(uint160 sqrtPriceX96, int24 tick);\\n\\n /// @notice Emitted when liquidity is minted for a given position\\n /// @param sender The address that minted the liquidity\\n /// @param owner The owner of the position and recipient of any minted liquidity\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity minted to the position range\\n /// @param amount0 How much token0 was required for the minted liquidity\\n /// @param amount1 How much token1 was required for the minted liquidity\\n event Mint(\\n address sender,\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted when fees are collected by the owner of a position\\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\n /// @param owner The owner of the position for which fees are collected\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount0 The amount of token0 fees collected\\n /// @param amount1 The amount of token1 fees collected\\n event Collect(\\n address indexed owner,\\n address recipient,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount0,\\n uint128 amount1\\n );\\n\\n /// @notice Emitted when a position's liquidity is removed\\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\n /// @param owner The owner of the position for which liquidity is removed\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity to remove\\n /// @param amount0 The amount of token0 withdrawn\\n /// @param amount1 The amount of token1 withdrawn\\n event Burn(\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted by the pool for any swaps between token0 and token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the output of the swap\\n /// @param amount0 The delta of the token0 balance of the pool\\n /// @param amount1 The delta of the token1 balance of the pool\\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\n /// @param liquidity The liquidity of the pool after the swap\\n /// @param tick The log base 1.0001 of price of the pool after the swap\\n event Swap(\\n address indexed sender,\\n address indexed recipient,\\n int256 amount0,\\n int256 amount1,\\n uint160 sqrtPriceX96,\\n uint128 liquidity,\\n int24 tick\\n );\\n\\n /// @notice Emitted by the pool for any flashes of token0/token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the tokens from flash\\n /// @param amount0 The amount of token0 that was flashed\\n /// @param amount1 The amount of token1 that was flashed\\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\n event Flash(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1,\\n uint256 paid0,\\n uint256 paid1\\n );\\n\\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\n /// just before a mint/swap/burn.\\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\n event IncreaseObservationCardinalityNext(\\n uint16 observationCardinalityNextOld,\\n uint16 observationCardinalityNextNew\\n );\\n\\n /// @notice Emitted when the protocol fee is changed by the pool\\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\\n /// @param feeProtocol0New The updated value of the token0 protocol fee\\n /// @param feeProtocol1New The updated value of the token1 protocol fee\\n event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\n\\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\n /// @param sender The address that collects the protocol fees\\n /// @param recipient The address that receives the collected protocol fees\\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\\n event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that never changes\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\ninterface IUniswapV3PoolImmutables {\\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\n /// @return The contract address\\n function factory() external view returns (address);\\n\\n /// @notice The first of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token0() external view returns (address);\\n\\n /// @notice The second of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token1() external view returns (address);\\n\\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\n /// @return The fee\\n function fee() external view returns (uint24);\\n\\n /// @notice The pool tick spacing\\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\n /// This value is an int24 to avoid casting even though it is always positive.\\n /// @return The tick spacing\\n function tickSpacing() external view returns (int24);\\n\\n /// @notice The maximum amount of position liquidity that can use any tick in the range\\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\n /// @return The max amount of liquidity per tick\\n function maxLiquidityPerTick() external view returns (uint128);\\n}\\n\",\"keccak256\":\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissioned pool actions\\n/// @notice Contains pool methods that may only be called by the factory owner\\ninterface IUniswapV3PoolOwnerActions {\\n /// @notice Set the denominator of the protocol's % share of the fees\\n /// @param feeProtocol0 new protocol fee for token0 of the pool\\n /// @param feeProtocol1 new protocol fee for token1 of the pool\\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\n\\n /// @notice Collect the protocol fee accrued to the pool\\n /// @param recipient The address to which collected protocol fees should be sent\\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\n /// @return amount0 The protocol fee collected in token0\\n /// @return amount1 The protocol fee collected in token1\\n function collectProtocol(\\n address recipient,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n /// when accessed externally.\\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n /// boundary.\\n /// observationIndex The index of the last oracle observation that was written,\\n /// observationCardinality The current maximum number of observations stored in the pool,\\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n /// feeProtocol The protocol fee for both tokens of the pool.\\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n /// unlocked Whether the pool is currently locked to reentrancy\\n function slot0()\\n external\\n view\\n returns (\\n uint160 sqrtPriceX96,\\n int24 tick,\\n uint16 observationIndex,\\n uint16 observationCardinality,\\n uint16 observationCardinalityNext,\\n uint8 feeProtocol,\\n bool unlocked\\n );\\n\\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n /// @notice The amounts of token0 and token1 that are owed to the protocol\\n /// @dev Protocol fees will never exceed uint128 max in either token\\n function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n /// @notice The currently in range liquidity available to the pool\\n /// @dev This value has no relationship to the total liquidity across all ticks\\n function liquidity() external view returns (uint128);\\n\\n /// @notice Look up information about a specific tick in the pool\\n /// @param tick The tick to look up\\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n /// tick upper,\\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n /// a specific position.\\n function ticks(int24 tick)\\n external\\n view\\n returns (\\n uint128 liquidityGross,\\n int128 liquidityNet,\\n uint256 feeGrowthOutside0X128,\\n uint256 feeGrowthOutside1X128,\\n int56 tickCumulativeOutside,\\n uint160 secondsPerLiquidityOutsideX128,\\n uint32 secondsOutside,\\n bool initialized\\n );\\n\\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n /// @notice Returns the information about a position by the position's key\\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n /// @return _liquidity The amount of liquidity in the position,\\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n function positions(bytes32 key)\\n external\\n view\\n returns (\\n uint128 _liquidity,\\n uint256 feeGrowthInside0LastX128,\\n uint256 feeGrowthInside1LastX128,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n );\\n\\n /// @notice Returns data about a specific observation index\\n /// @param index The element of the observations array to fetch\\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n /// ago, rather than at a specific index in the array.\\n /// @return blockTimestamp The timestamp of the observation,\\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n /// Returns initialized whether the observation has been initialized and the values are safe to use\\n function observations(uint256 index)\\n external\\n view\\n returns (\\n uint32 blockTimestamp,\\n int56 tickCumulative,\\n uint160 secondsPerLiquidityCumulativeX128,\\n bool initialized\\n );\\n}\\n\",\"keccak256\":\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.4.0;\\n\\n/// @title FixedPoint96\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\n/// @dev Used in SqrtPriceMath.sol\\nlibrary FixedPoint96 {\\n uint8 internal constant RESOLUTION = 96;\\n uint256 internal constant Q96 = 0x1000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/FullMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n /// @notice Calculates floor(a\\u00d7b\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n /// @param a The multiplicand\\n /// @param b The multiplier\\n /// @param denominator The divisor\\n /// @return result The 256-bit result\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\n function mulDiv(\\n uint256 a,\\n uint256 b,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = a * b\\n // Compute the product mod 2**256 and mod 2**256 - 1\\n // then use the Chinese Remainder Theorem to reconstruct\\n // 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(a, b, not(0))\\n prod0 := mul(a, b)\\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 require(denominator > 0);\\n assembly {\\n result := div(prod0, denominator)\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2**256.\\n // 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 // Compute remainder using mulmod\\n uint256 remainder;\\n assembly {\\n remainder := mulmod(a, b, denominator)\\n }\\n // Subtract 256 bit number from 512 bit number\\n assembly {\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator\\n // Compute largest power of two divisor of denominator.\\n // Always >= 1.\\n uint256 twos = -denominator & denominator;\\n // Divide denominator by power of two\\n assembly {\\n denominator := div(denominator, twos)\\n }\\n\\n // Divide [prod1 prod0] by the factors of two\\n assembly {\\n prod0 := div(prod0, twos)\\n }\\n // Shift in bits from prod1 into prod0. For this we need\\n // to flip `twos` such that it is 2**256 / twos.\\n // If twos is zero, then it becomes one\\n assembly {\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2**256\\n // Now that denominator is an odd number, it has an inverse\\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n // Compute the inverse by starting with a seed that is correct\\n // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n uint256 inv = (3 * denominator) ^ 2;\\n // Now use Newton-Raphson iteration to improve the precision.\\n // Thanks to Hensel's lifting lemma, this also works in modular\\n // arithmetic, doubling the correct bits in each step.\\n inv *= 2 - denominator * inv; // inverse mod 2**8\\n inv *= 2 - denominator * inv; // inverse mod 2**16\\n inv *= 2 - denominator * inv; // inverse mod 2**32\\n inv *= 2 - denominator * inv; // inverse mod 2**64\\n inv *= 2 - denominator * inv; // inverse mod 2**128\\n inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n // Because the division is now exact we can divide by multiplying\\n // with the modular inverse of denominator. This will give us the\\n // correct result modulo 2**256. Since the precoditions guarantee\\n // that the outcome is less than 2**256, this is the final result.\\n // We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inv;\\n return result;\\n }\\n\\n /// @notice Calculates ceil(a\\u00d7b\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n /// @param a The multiplicand\\n /// @param b The multiplier\\n /// @param denominator The divisor\\n /// @return result The 256-bit result\\n function mulDivRoundingUp(\\n uint256 a,\\n uint256 b,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n result = mulDiv(a, b, denominator);\\n if (mulmod(a, b, denominator) > 0) {\\n require(result < type(uint256).max);\\n result++;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\",\"license\":\"MIT\"},\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n /// @notice Returns x + y, reverts if sum overflows uint256\\n /// @param x The augend\\n /// @param y The addend\\n /// @return z The sum of x and y\\n function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n require((z = x + y) >= x);\\n }\\n\\n /// @notice Returns x - y, reverts if underflows\\n /// @param x The minuend\\n /// @param y The subtrahend\\n /// @return z The difference of x and y\\n function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n require((z = x - y) <= x);\\n }\\n\\n /// @notice Returns x * y, reverts if overflows\\n /// @param x The multiplicand\\n /// @param y The multiplier\\n /// @return z The product of x and y\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n require(x == 0 || (z = x * y) / x == y);\\n }\\n\\n /// @notice Returns x + y, reverts if overflows or underflows\\n /// @param x The augend\\n /// @param y The addend\\n /// @return z The sum of x and y\\n function add(int256 x, int256 y) internal pure returns (int256 z) {\\n require((z = x + y) >= x == (y >= 0));\\n }\\n\\n /// @notice Returns x - y, reverts if overflows or underflows\\n /// @param x The minuend\\n /// @param y The subtrahend\\n /// @return z The difference of x and y\\n function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n require((z = x - y) <= x == (y >= 0));\\n }\\n}\\n\",\"keccak256\":\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Safe casting methods\\n/// @notice Contains methods for safely casting between types\\nlibrary SafeCast {\\n /// @notice Cast a uint256 to a uint160, revert on overflow\\n /// @param y The uint256 to be downcasted\\n /// @return z The downcasted integer, now type uint160\\n function toUint160(uint256 y) internal pure returns (uint160 z) {\\n require((z = uint160(y)) == y);\\n }\\n\\n /// @notice Cast a int256 to a int128, revert on overflow or underflow\\n /// @param y The int256 to be downcasted\\n /// @return z The downcasted integer, now type int128\\n function toInt128(int256 y) internal pure returns (int128 z) {\\n require((z = int128(y)) == y);\\n }\\n\\n /// @notice Cast a uint256 to a int256, revert on overflow\\n /// @param y The uint256 to be casted\\n /// @return z The casted integer, now type int256\\n function toInt256(uint256 y) internal pure returns (int256 z) {\\n require(y < 2**255);\\n z = int256(y);\\n }\\n}\\n\",\"keccak256\":\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/TickMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n int24 internal constant MIN_TICK = -887272;\\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n /// @dev Throws if |tick| > max tick\\n /// @param tick The input tick for the above formula\\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n /// at the given tick\\n function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n require(absTick <= uint256(MAX_TICK), 'T');\\n\\n uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n }\\n\\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n /// ever return.\\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n // second inequality must be < because the price can never reach the price at the max tick\\n require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n uint256 r = ratio;\\n uint256 msb = 0;\\n\\n assembly {\\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(5, gt(r, 0xFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(4, gt(r, 0xFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(3, gt(r, 0xFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(2, gt(r, 0xF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(1, gt(r, 0x3))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := gt(r, 0x1)\\n msb := or(msb, f)\\n }\\n\\n if (msb >= 128) r = ratio >> (msb - 127);\\n else r = ratio << (127 - msb);\\n\\n int256 log_2 = (int256(msb) - 128) << 64;\\n\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(63, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(62, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(61, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(60, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(59, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(58, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(57, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(56, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(55, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(54, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(53, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(52, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(51, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(50, f))\\n }\\n\\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n }\\n}\\n\",\"keccak256\":\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math functions that do not check inputs or outputs\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\nlibrary UnsafeMath {\\n /// @notice Returns ceil(x / y)\\n /// @dev division by 0 has unspecified behavior, and must be checked externally\\n /// @param x The dividend\\n /// @param y The divisor\\n /// @return z The quotient, ceil(x / y)\\n function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n assembly {\\n z := add(div(x, y), gt(mod(x, y), 0))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n /// @notice The permit typehash used in the permit signature\\n /// @return The typehash for the permit\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n /// @notice The domain separator used in the permit signature\\n /// @return The domain seperator used in encoding of permit signature\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n /// @notice Approve of a specific token ID for spending by spender via signature\\n /// @param spender The account that is being approved\\n /// @param tokenId The ID of the token that is being approved for spending\\n /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n function permit(\\n address spender,\\n uint256 tokenId,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external payable;\\n}\\n\",\"keccak256\":\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n IPoolInitializer,\\n IPeripheryPayments,\\n IPeripheryImmutableState,\\n IERC721Metadata,\\n IERC721Enumerable,\\n IERC721Permit\\n{\\n /// @notice Emitted when liquidity is increased for a position NFT\\n /// @dev Also emitted when a token is minted\\n /// @param tokenId The ID of the token for which liquidity was increased\\n /// @param liquidity The amount by which liquidity for the NFT position was increased\\n /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n /// @notice Emitted when liquidity is decreased for a position NFT\\n /// @param tokenId The ID of the token for which liquidity was decreased\\n /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n /// @notice Emitted when tokens are collected for a position NFT\\n /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n /// @param tokenId The ID of the token for which underlying tokens were collected\\n /// @param recipient The address of the account that received the collected tokens\\n /// @param amount0 The amount of token0 owed to the position that was collected\\n /// @param amount1 The amount of token1 owed to the position that was collected\\n event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n /// @notice Returns the position information associated with a given token ID.\\n /// @dev Throws if the token ID is not valid.\\n /// @param tokenId The ID of the token that represents the position\\n /// @return nonce The nonce for permits\\n /// @return operator The address that is approved for spending\\n /// @return token0 The address of the token0 for a specific pool\\n /// @return token1 The address of the token1 for a specific pool\\n /// @return fee The fee associated with the pool\\n /// @return tickLower The lower end of the tick range for the position\\n /// @return tickUpper The higher end of the tick range for the position\\n /// @return liquidity The liquidity of the position\\n /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n function positions(uint256 tokenId)\\n external\\n view\\n returns (\\n uint96 nonce,\\n address operator,\\n address token0,\\n address token1,\\n uint24 fee,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity,\\n uint256 feeGrowthInside0LastX128,\\n uint256 feeGrowthInside1LastX128,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n );\\n\\n struct MintParams {\\n address token0;\\n address token1;\\n uint24 fee;\\n int24 tickLower;\\n int24 tickUpper;\\n uint256 amount0Desired;\\n uint256 amount1Desired;\\n uint256 amount0Min;\\n uint256 amount1Min;\\n address recipient;\\n uint256 deadline;\\n }\\n\\n /// @notice Creates a new position wrapped in a NFT\\n /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n /// a method does not exist, i.e. the pool is assumed to be initialized.\\n /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n /// @return tokenId The ID of the token that represents the minted position\\n /// @return liquidity The amount of liquidity for this position\\n /// @return amount0 The amount of token0\\n /// @return amount1 The amount of token1\\n function mint(MintParams calldata params)\\n external\\n payable\\n returns (\\n uint256 tokenId,\\n uint128 liquidity,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n struct IncreaseLiquidityParams {\\n uint256 tokenId;\\n uint256 amount0Desired;\\n uint256 amount1Desired;\\n uint256 amount0Min;\\n uint256 amount1Min;\\n uint256 deadline;\\n }\\n\\n /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n /// @param params tokenId The ID of the token for which liquidity is being increased,\\n /// amount0Desired The desired amount of token0 to be spent,\\n /// amount1Desired The desired amount of token1 to be spent,\\n /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n /// deadline The time by which the transaction must be included to effect the change\\n /// @return liquidity The new liquidity amount as a result of the increase\\n /// @return amount0 The amount of token0 to acheive resulting liquidity\\n /// @return amount1 The amount of token1 to acheive resulting liquidity\\n function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n external\\n payable\\n returns (\\n uint128 liquidity,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n struct DecreaseLiquidityParams {\\n uint256 tokenId;\\n uint128 liquidity;\\n uint256 amount0Min;\\n uint256 amount1Min;\\n uint256 deadline;\\n }\\n\\n /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n /// amount The amount by which liquidity will be decreased,\\n /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n /// deadline The time by which the transaction must be included to effect the change\\n /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n external\\n payable\\n returns (uint256 amount0, uint256 amount1);\\n\\n struct CollectParams {\\n uint256 tokenId;\\n address recipient;\\n uint128 amount0Max;\\n uint128 amount1Max;\\n }\\n\\n /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n /// recipient The account that should receive the tokens,\\n /// amount0Max The maximum amount of token0 to collect,\\n /// amount1Max The maximum amount of token1 to collect\\n /// @return amount0 The amount of fees collected in token0\\n /// @return amount1 The amount of fees collected in token1\\n function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n /// must be collected first.\\n /// @param tokenId The ID of the token that is being burned\\n function burn(uint256 tokenId) external payable;\\n}\\n\",\"keccak256\":\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n /// @return Returns the address of the Uniswap V3 factory\\n function factory() external view returns (address);\\n\\n /// @return Returns the address of WETH9\\n function WETH9() external view returns (address);\\n}\\n\",\"keccak256\":\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n /// @param recipient The address receiving ETH\\n function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n /// that use ether for the input amount\\n function refundETH() external payable;\\n\\n /// @notice Transfers the full amount of a token held by this contract to recipient\\n /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n /// @param token The contract address of the token which will be transferred to `recipient`\\n /// @param amountMinimum The minimum amount of token required for a transfer\\n /// @param recipient The destination address of the token\\n function sweepToken(\\n address token,\\n uint256 amountMinimum,\\n address recipient\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n /// @param token0 The contract address of token0 of the pool\\n /// @param token1 The contract address of token1 of the pool\\n /// @param fee The fee amount of the v3 pool for the specified token pair\\n /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n function createAndInitializePoolIfNecessary(\\n address token0,\\n address token1,\\n uint24 fee,\\n uint160 sqrtPriceX96\\n ) external payable returns (address pool);\\n}\\n\",\"keccak256\":\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gon\\u00e7alo S\\u00e1 \\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n require(_length + 31 >= _length, 'slice_overflow');\\n require(_start + _length >= _start, 'slice_overflow');\\n require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n require(_start + 20 >= _start, 'toAddress_overflow');\\n require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n }\\n\\n return tempAddress;\\n }\\n\\n function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n require(_start + 3 >= _start, 'toUint24_overflow');\\n require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n uint24 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0x3), _start))\\n }\\n\\n return tempUint;\\n }\\n}\\n\",\"keccak256\":\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n /// @notice Returns the address of a valid Uniswap V3 Pool\\n /// @param factory The contract address of the Uniswap V3 factory\\n /// @param tokenA The contract address of either token0 or token1\\n /// @param tokenB The contract address of the other token\\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n /// @return pool The V3 pool contract address\\n function verifyCallback(\\n address factory,\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n ) internal view returns (IUniswapV3Pool pool) {\\n return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n }\\n\\n /// @notice Returns the address of a valid Uniswap V3 Pool\\n /// @param factory The contract address of the Uniswap V3 factory\\n /// @param poolKey The identifying key of the V3 pool\\n /// @return pool The V3 pool contract address\\n function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n internal\\n view\\n returns (IUniswapV3Pool pool)\\n {\\n pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n require(msg.sender == address(pool));\\n }\\n}\\n\",\"keccak256\":\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/libraries/Path.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n using BytesLib for bytes;\\n\\n /// @dev The length of the bytes encoded address\\n uint256 private constant ADDR_SIZE = 20;\\n /// @dev The length of the bytes encoded fee\\n uint256 private constant FEE_SIZE = 3;\\n\\n /// @dev The offset of a single token address and pool fee\\n uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n /// @dev The offset of an encoded pool key\\n uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n /// @dev The minimum length of an encoding that contains 2 or more pools\\n uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n /// @notice Returns true iff the path contains two or more pools\\n /// @param path The encoded swap path\\n /// @return True if path contains two or more pools, otherwise false\\n function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n }\\n\\n /// @notice Returns the number of pools in the path\\n /// @param path The encoded swap path\\n /// @return The number of pools in the path\\n function numPools(bytes memory path) internal pure returns (uint256) {\\n // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n }\\n\\n /// @notice Decodes the first pool in path\\n /// @param path The bytes encoded swap path\\n /// @return tokenA The first token of the given pool\\n /// @return tokenB The second token of the given pool\\n /// @return fee The fee level of the pool\\n function decodeFirstPool(bytes memory path)\\n internal\\n pure\\n returns (\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n )\\n {\\n tokenA = path.toAddress(0);\\n fee = path.toUint24(ADDR_SIZE);\\n tokenB = path.toAddress(NEXT_OFFSET);\\n }\\n\\n /// @notice Gets the segment corresponding to the first pool in the path\\n /// @param path The bytes encoded swap path\\n /// @return The segment containing all data necessary to target the first pool in the path\\n function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n return path.slice(0, POP_OFFSET);\\n }\\n\\n /// @notice Skips a token + fee element from the buffer and returns the remainder\\n /// @param path The swap path\\n /// @return The remaining token + fee elements in the path\\n function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n }\\n}\\n\",\"keccak256\":\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n /// @notice The identifying key of the pool\\n struct PoolKey {\\n address token0;\\n address token1;\\n uint24 fee;\\n }\\n\\n /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n /// @param tokenA The first token of a pool, unsorted\\n /// @param tokenB The second token of a pool, unsorted\\n /// @param fee The fee level of the pool\\n /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n function getPoolKey(\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n ) internal pure returns (PoolKey memory) {\\n if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n }\\n\\n /// @notice Deterministically computes the pool address given the factory and PoolKey\\n /// @param factory The Uniswap V3 factory contract address\\n /// @param key The PoolKey\\n /// @return pool The contract address of the V3 pool\\n function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n require(key.token0 < key.token1);\\n pool = address(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex'ff',\\n factory,\\n keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n POOL_INIT_CODE_HASH\\n )\\n )\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n function ethQuoteCurrencyPool() external view returns (address);\\n\\n function feeRate() external view returns (uint256);\\n\\n function getFee(\\n uint256 _vaultId,\\n uint256 _wPowerPerpAmount,\\n uint256 _collateralAmount\\n ) external view returns (uint256);\\n\\n function quoteCurrency() external view returns (address);\\n\\n function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n function shortPowerPerp() external view returns (address);\\n\\n function wPowerPerp() external view returns (address);\\n\\n function wPowerPerpPool() external view returns (address);\\n\\n function oracle() external view returns (address);\\n\\n function weth() external view returns (address);\\n\\n function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n function mintPowerPerpAmount(\\n uint256 _vaultId,\\n uint256 _powerPerpAmount,\\n uint256 _uniTokenId\\n ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n function mintWPowerPerpAmount(\\n uint256 _vaultId,\\n uint256 _wPowerPerpAmount,\\n uint256 _uniTokenId\\n ) external payable returns (uint256 vaultId);\\n\\n /**\\n * Deposit collateral into a vault\\n */\\n function deposit(uint256 _vaultId) external payable;\\n\\n /**\\n * Withdraw collateral from a vault.\\n */\\n function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n function burnWPowerPerpAmount(\\n uint256 _vaultId,\\n uint256 _wPowerPerpAmount,\\n uint256 _withdrawAmount\\n ) external;\\n\\n function burnPowerPerpAmount(\\n uint256 _vaultId,\\n uint256 _powerPerpAmount,\\n uint256 _withdrawAmount\\n ) external returns (uint256 wPowerPerpAmount);\\n\\n function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n /**\\n * External function to update the normalized factor as a way to pay funding.\\n */\\n function applyFunding() external;\\n\\n function redeemShort(uint256 _vaultId) external;\\n\\n function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n function isShutDown() external returns (bool);\\n\\n function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\",\"keccak256\":\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Detailed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\",\"license\":\"MIT\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n function getHistoricalTwap(\\n address _pool,\\n address _base,\\n address _quote,\\n uint32 _period,\\n uint32 _periodToHistoricPrice\\n ) external view returns (uint256);\\n\\n function getTwap(\\n address _pool,\\n address _base,\\n address _quote,\\n uint32 _period,\\n bool _checkPeriod\\n ) external view returns (uint256);\\n\\n function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n external\\n view\\n returns (int24 timeWeightedAverageTick);\\n}\\n\",\"keccak256\":\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\",\"license\":\"MIT\"},\"contracts/interfaces/IShortPowerPerp.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n function nextId() external view returns (uint256);\\n\\n function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\",\"keccak256\":\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\",\"license\":\"MIT\"},\"contracts/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n}\\n\",\"keccak256\":\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\",\"license\":\"MIT\"},\"contracts/interfaces/IWPowerPerp.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n function mint(address _account, uint256 _amount) external;\\n\\n function burn(address _account, uint256 _amount) external;\\n}\\n\",\"keccak256\":\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\",\"license\":\"MIT\"},\"contracts/libs/SqrtPriceMathPartial.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n /// @notice Gets the amount0 delta between two prices\\n /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n /// @param sqrtRatioAX96 A sqrt price\\n /// @param sqrtRatioBX96 Another sqrt price\\n /// @param liquidity The amount of usable liquidity\\n /// @param roundUp Whether to round the amount up or down\\n /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n function getAmount0Delta(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity,\\n bool roundUp\\n ) external pure returns (uint256 amount0) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n require(sqrtRatioAX96 > 0);\\n\\n return\\n roundUp\\n ? UnsafeMath.divRoundingUp(\\n FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n sqrtRatioAX96\\n )\\n : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n }\\n\\n /// @notice Gets the amount1 delta between two prices\\n /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n /// @param sqrtRatioAX96 A sqrt price\\n /// @param sqrtRatioBX96 Another sqrt price\\n /// @param liquidity The amount of usable liquidity\\n /// @param roundUp Whether to round the amount up, or down\\n /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n function getAmount1Delta(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity,\\n bool roundUp\\n ) external pure returns (uint256 amount1) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n return\\n roundUp\\n ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n }\\n}\\n\",\"keccak256\":\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libs/TickMathExternal.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n int24 internal constant MIN_TICK = -887272;\\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n /// @dev Throws if |tick| > max tick\\n /// @param tick The input tick for the above formula\\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n /// at the given tick\\n function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n }\\n\\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n /// ever return.\\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n // second inequality must be < because the price can never reach the price at the max tick\\n require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n uint256 r = ratio;\\n uint256 msb = 0;\\n\\n assembly {\\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(5, gt(r, 0xFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(4, gt(r, 0xFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(3, gt(r, 0xFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(2, gt(r, 0xF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(1, gt(r, 0x3))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := gt(r, 0x1)\\n msb := or(msb, f)\\n }\\n\\n if (msb >= 128) r = ratio >> (msb - 127);\\n else r = ratio << (127 - msb);\\n\\n int256 log_2 = (int256(msb) - 128) << 64;\\n\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(63, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(62, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(61, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(60, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(59, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(58, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(57, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(56, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(55, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(54, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(53, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(52, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(51, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(50, f))\\n }\\n\\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n }\\n}\\n\",\"keccak256\":\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libs/Uint256Casting.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n /**\\n * @notice cast a uint256 to a uint128, revert on overflow\\n * @param y the uint256 to be downcasted\\n * @return z the downcasted integer, now type uint128\\n */\\n function toUint128(uint256 y) internal pure returns (uint128 z) {\\n require((z = uint128(y)) == y, \\\"OF128\\\");\\n }\\n\\n /**\\n * @notice cast a uint256 to a uint96, revert on overflow\\n * @param y the uint256 to be downcasted\\n * @return z the downcasted integer, now type uint96\\n */\\n function toUint96(uint256 y) internal pure returns (uint96 z) {\\n require((z = uint96(y)) == y, \\\"OF96\\\");\\n }\\n\\n /**\\n * @notice cast a uint256 to a uint32, revert on overflow\\n * @param y the uint256 to be downcasted\\n * @return z the downcasted integer, now type uint32\\n */\\n function toUint32(uint256 y) internal pure returns (uint32 z) {\\n require((z = uint32(y)) == y, \\\"OF32\\\");\\n }\\n}\\n\",\"keccak256\":\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\",\"license\":\"MIT\"},\"contracts/libs/VaultLib.sol\":{\"content\":\"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n using SafeMath for uint256;\\n using Uint256Casting for uint256;\\n\\n uint256 constant ONE_ONE = 1e36;\\n\\n // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n uint256 public constant CR_NUMERATOR = 3;\\n uint256 public constant CR_DENOMINATOR = 2;\\n\\n struct Vault {\\n // the address that can update the vault\\n address operator;\\n // uniswap position token id deposited into the vault as collateral\\n // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n uint32 NftCollateralId;\\n // amount of eth (wei) used in the vault as collateral\\n // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n uint96 collateralAmount;\\n // amount of wPowerPerp minted from the vault\\n uint128 shortAmount;\\n }\\n\\n /**\\n * @notice add eth collateral to a vault\\n * @param _vault in-memory vault\\n * @param _amount amount of eth to add\\n */\\n function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n }\\n\\n /**\\n * @notice add uniswap position token collateral to a vault\\n * @param _vault in-memory vault\\n * @param _tokenId uniswap position token id\\n */\\n function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n require(_tokenId != 0, \\\"C23\\\");\\n _vault.NftCollateralId = _tokenId.toUint32();\\n }\\n\\n /**\\n * @notice remove eth collateral from a vault\\n * @param _vault in-memory vault\\n * @param _amount amount of eth to remove\\n */\\n function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n }\\n\\n /**\\n * @notice remove uniswap position token collateral from a vault\\n * @param _vault in-memory vault\\n */\\n function removeUniNftCollateral(Vault memory _vault) internal pure {\\n require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n _vault.NftCollateralId = 0;\\n }\\n\\n /**\\n * @notice add debt to vault\\n * @param _vault in-memory vault\\n * @param _amount amount of debt to add\\n */\\n function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n }\\n\\n /**\\n * @notice remove debt from vault\\n * @param _vault in-memory vault\\n * @param _amount amount of debt to remove\\n */\\n function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n }\\n\\n /**\\n * @notice check if a vault is properly collateralized\\n * @param _vault the vault we want to check\\n * @param _positionManager address of the uniswap position manager\\n * @param _normalizationFactor current _normalizationFactor\\n * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n * @param _minCollateral minimum collateral that needs to be in a vault\\n * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n * @return true if the vault is sufficiently collateralized\\n * @return true if the vault is considered as a dust vault\\n */\\n function getVaultStatus(\\n Vault memory _vault,\\n address _positionManager,\\n uint256 _normalizationFactor,\\n uint256 _ethQuoteCurrencyPrice,\\n uint256 _minCollateral,\\n int24 _wsqueethPoolTick,\\n bool _isWethToken0\\n ) internal view returns (bool, bool) {\\n if (_vault.shortAmount == 0) return (true, false);\\n\\n uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n ONE_ONE\\n );\\n uint256 totalCollateral = _getEffectiveCollateral(\\n _vault,\\n _positionManager,\\n _normalizationFactor,\\n _ethQuoteCurrencyPrice,\\n _wsqueethPoolTick,\\n _isWethToken0\\n );\\n\\n bool isDust = totalCollateral < _minCollateral;\\n bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n return (isAboveWater, isDust);\\n }\\n\\n /**\\n * @notice get the total effective collateral of a vault, which is:\\n * collateral amount + uniswap position token equivelent amount in eth\\n * @param _vault the vault we want to check\\n * @param _positionManager address of the uniswap position manager\\n * @param _normalizationFactor current _normalizationFactor\\n * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n * @return the total worth of collateral in the vault\\n */\\n function _getEffectiveCollateral(\\n Vault memory _vault,\\n address _positionManager,\\n uint256 _normalizationFactor,\\n uint256 _ethQuoteCurrencyPrice,\\n int24 _wsqueethPoolTick,\\n bool _isWethToken0\\n ) internal view returns (uint256) {\\n if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n _positionManager,\\n _vault.NftCollateralId,\\n _wsqueethPoolTick,\\n _isWethToken0\\n );\\n // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n ONE_ONE\\n );\\n // add eth value from uniswap position token as collateral\\n return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n }\\n\\n /**\\n * @notice determine how much eth / wPowerPerp the uniswap position contains\\n * @param _positionManager address of the uniswap position manager\\n * @param _tokenId uniswap position token id\\n * @param _wPowerPerpPoolTick current price tick\\n * @param _isWethToken0 whether weth is token0 in the pool\\n * @return ethAmount the eth amount this LP token contains\\n * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n */\\n function _getUniPositionBalances(\\n address _positionManager,\\n uint256 _tokenId,\\n int24 _wPowerPerpPoolTick,\\n bool _isWethToken0\\n ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n (\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n tickLower,\\n tickUpper,\\n _wPowerPerpPoolTick,\\n liquidity\\n );\\n\\n return\\n _isWethToken0\\n ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n }\\n\\n /**\\n * @notice get uniswap position token info\\n * @param _positionManager address of the uniswap position position manager\\n * @param _tokenId uniswap position token id\\n * @return tickLower lower tick of the position\\n * @return tickUpper upper tick of the position\\n * @return liquidity raw liquidity amount of the position\\n * @return tokensOwed0 amount of token 0 can be collected as fee\\n * @return tokensOwed1 amount of token 1 can be collected as fee\\n */\\n function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n internal\\n view\\n returns (\\n int24,\\n int24,\\n uint128,\\n uint128,\\n uint128\\n )\\n {\\n INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n (\\n ,\\n ,\\n ,\\n ,\\n ,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity,\\n ,\\n ,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n ) = positionManager.positions(_tokenId);\\n return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n }\\n\\n /**\\n * @notice get balances of token0 / token1 in a uniswap position\\n * @dev knowing liquidity, tick range, and current tick gives balances\\n * @param _tickLower address of the uniswap position manager\\n * @param _tickUpper uniswap position token id\\n * @param _tick current price tick used for calculation\\n * @return amount0 the amount of token0 in the uniswap position token\\n * @return amount1 the amount of token1 in the uniswap position token\\n */\\n function _getToken0Token1Balances(\\n int24 _tickLower,\\n int24 _tickUpper,\\n int24 _tick,\\n uint128 _liquidity\\n ) internal pure returns (uint256 amount0, uint256 amount1) {\\n // get the current price and tick from wPowerPerp pool\\n uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n if (_tick < _tickLower) {\\n amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n _liquidity,\\n true\\n );\\n } else if (_tick < _tickUpper) {\\n amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n sqrtPriceX96,\\n TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n _liquidity,\\n true\\n );\\n amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n sqrtPriceX96,\\n _liquidity,\\n true\\n );\\n } else {\\n amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n _liquidity,\\n true\\n );\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\",\"license\":\"GPL-2.0-or-later\"},\"contracts/periphery/ControllerHelper.sol\":{\"content\":\"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n using SafeMath for uint256;\\n using Address for address payable;\\n\\n bool private immutable isWethToken0;\\n address private immutable controller;\\n address private immutable shortPowerPerp;\\n address private immutable wPowerPerp;\\n address private immutable weth;\\n address private immutable nonfungiblePositionManager;\\n\\n constructor(\\n address _controller,\\n address _nonfungiblePositionManager,\\n address _uniswapFactory,\\n address _exec,\\n address _euler,\\n address _dToken\\n )\\n UniswapControllerHelper(_uniswapFactory)\\n EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n {\\n controller = _controller;\\n shortPowerPerp = IController(_controller).shortPowerPerp();\\n wPowerPerp = IController(_controller).wPowerPerp();\\n weth = IController(_controller).weth();\\n nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n }\\n\\n /**\\n * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n * @return returns received selector\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @notice receive function to allow ETH transfer to this contract\\n */\\n receive() external payable {}\\n\\n /**\\n * @notice flash close position and buy long squeeth\\n * @dev this function\\n * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n */\\n function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n external\\n payable\\n {\\n _checkAccess(_params.vaultId);\\n\\n require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n wrapInternal(msg.value);\\n\\n _exactOutFlashSwap(\\n weth,\\n wPowerPerp,\\n _params.poolFee,\\n _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n _params.maxToPay,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n abi.encode(_params)\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice sell long wPowerPerp and flashswap mint short position\\n * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n */\\n function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n external\\n payable\\n {\\n if (_params.vaultId != 0) {\\n _checkAccess(_params.vaultId);\\n }\\n\\n wrapInternal(msg.value);\\n IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n // flashswap and mint short position\\n uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n _exactInFlashSwap(\\n wPowerPerp,\\n weth,\\n _params.poolFee,\\n totalAmountIn,\\n _params.minToReceive,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n abi.encode(_params)\\n );\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice close short position with user Uniswap v3 LP NFT\\n * @dev user should approve this contract for Uni NFT transfer\\n * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n */\\n function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n external\\n payable\\n {\\n _checkAccess(_params.vaultId);\\n\\n INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _params.tokenId\\n );\\n\\n wrapInternal(msg.value);\\n\\n // close LP position\\n (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: _params.tokenId,\\n liquidity: _params.liquidity,\\n liquidityPercentage: _params.liquidityPercentage,\\n amount0Min: _params.amount0Min,\\n amount1Min: _params.amount1Min\\n }),\\n isWethToken0\\n );\\n\\n // if LP position is not fully closed, redeposit in vault or send back to user\\n ControllerHelperUtil.checkClosedLp(\\n msg.sender,\\n controller,\\n nonfungiblePositionManager,\\n 0,\\n _params.tokenId,\\n _params.liquidityPercentage\\n );\\n // burn vault debt using amounts withdrawn from LP position\\n _closeShortWithAmountsFromLp(\\n _params.vaultId,\\n wPowerPerpAmountInLp,\\n _params.wPowerPerpAmountToBurn,\\n _params.collateralToWithdraw,\\n _params.limitPriceEthPerPowerPerp,\\n _params.poolFee,\\n _params.burnExactRemoved\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n external\\n payable\\n {\\n _checkAccess(_params.vaultId);\\n\\n wrapInternal(msg.value);\\n _flashLoan(\\n weth,\\n _params.collateralToFlashloan,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n abi.encode(_params)\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n * @param _params ControllerHelperDataType.MintAndLpParams struct\\n */\\n function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n if (_params.vaultId != 0) {\\n _checkAccess(_params.vaultId);\\n }\\n require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n wrapInternal(msg.value);\\n\\n (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n controller,\\n nonfungiblePositionManager,\\n wPowerPerp,\\n weth,\\n _params,\\n isWethToken0\\n );\\n\\n // if openeded new vault, transfer vault NFT to user\\n if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n */\\n function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n external\\n payable\\n {\\n if (_params.vaultId != 0) {\\n _checkAccess(_params.vaultId);\\n }\\n\\n wrapInternal(msg.value);\\n _flashLoan(\\n weth,\\n _params.collateralToFlashloan,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n abi.encode(_params)\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n */\\n function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _params.tokenId\\n );\\n\\n // close LP NFT and get Weth and WPowerPerp amounts\\n (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: _params.tokenId,\\n liquidity: _params.liquidity,\\n liquidityPercentage: _params.liquidityPercentage,\\n amount0Min: uint128(_params.amount0Min),\\n amount1Min: uint128(_params.amount1Min)\\n }),\\n isWethToken0\\n );\\n\\n ControllerHelperUtil.checkClosedLp(\\n msg.sender,\\n controller,\\n nonfungiblePositionManager,\\n 0,\\n _params.tokenId,\\n _params.liquidityPercentage\\n );\\n\\n if (wPowerPerpAmountInLp > 0) {\\n _exactInFlashSwap(\\n wPowerPerp,\\n weth,\\n _params.poolFee,\\n wPowerPerpAmountInLp,\\n _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n \\\"\\\"\\n );\\n }\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice Rebalance LP nft through trading\\n * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n */\\n function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n external\\n payable\\n {\\n wrapInternal(msg.value);\\n INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _params.tokenId\\n );\\n // close LP NFT and get Weth and WPowerPerp amounts\\n (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: _params.tokenId,\\n liquidity: _params.liquidity,\\n liquidityPercentage: 1e18,\\n amount0Min: uint128(_params.amount0Min),\\n amount1Min: uint128(_params.amount1Min)\\n }),\\n isWethToken0\\n );\\n\\n ControllerHelperUtil.checkClosedLp(\\n msg.sender,\\n controller,\\n nonfungiblePositionManager,\\n 0,\\n _params.tokenId,\\n 1e18\\n );\\n\\n uint256 wethAmountDesired;\\n uint256 wPowerPerpAmountDesired;\\n\\n if (isWethToken0) {\\n (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n _params.wPowerPerpPool,\\n _params.wethAmountDesired,\\n _params.wPowerPerpAmountDesired,\\n _params.lowerTick,\\n _params.upperTick,\\n isWethToken0\\n );\\n } else {\\n (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n _params.wPowerPerpPool,\\n _params.wethAmountDesired,\\n _params.wPowerPerpAmountDesired,\\n _params.lowerTick,\\n _params.upperTick,\\n isWethToken0\\n );\\n }\\n\\n if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n _exactOutFlashSwap(\\n weth,\\n wPowerPerp,\\n _params.poolFee,\\n wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n \\\"\\\"\\n );\\n } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n _exactInFlashSwap(\\n wPowerPerp,\\n weth,\\n _params.poolFee,\\n wPowerPerpExcess,\\n _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n \\\"\\\"\\n );\\n }\\n\\n // mint new position\\n ControllerHelperUtil.lpWPowerPerpPool(\\n nonfungiblePositionManager,\\n _params.wPowerPerpPool,\\n ControllerHelperDataType.LpWPowerPerpPoolParams({\\n recipient: msg.sender,\\n amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n amount0Min: _params.amount0DesiredMin,\\n amount1Min: _params.amount1DesiredMin,\\n lowerTick: _params.lowerTick,\\n upperTick: _params.upperTick\\n })\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n * @param _vaultId vault ID\\n * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n */\\n function rebalanceLpInVault(\\n uint256 _vaultId,\\n uint256 _collateralToFlashloan,\\n ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n ) external payable {\\n // check ownership\\n _checkAccess(_vaultId);\\n\\n wrapInternal(msg.value);\\n _flashLoan(\\n weth,\\n _collateralToFlashloan,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n abi.encode(_vaultId, _params)\\n );\\n\\n require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice checks if the msg.sender is the owener of the vault\\n * @param _vaultId vault ID\\n */\\n function _checkAccess(uint256 _vaultId) internal view {\\n require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n }\\n\\n /**\\n * @notice gets the shortAmount that has been minted from a vault\\n * @param _vaultId vault ID\\n * @return short amount from vault\\n */\\n\\n function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n return vault.shortAmount;\\n }\\n\\n function _flashCallback(\\n address _initiator,\\n address, /*_asset*/\\n uint256 _amount,\\n uint8 _callSource,\\n bytes memory _calldata\\n ) internal override {\\n if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n ) {\\n ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n _calldata,\\n (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n );\\n\\n (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n controller,\\n nonfungiblePositionManager,\\n wPowerPerp,\\n weth,\\n ControllerHelperDataType.MintAndLpParams({\\n recipient: address(this),\\n wPowerPerpPool: data.wPowerPerpPool,\\n vaultId: data.vaultId,\\n wPowerPerpAmount: data.wPowerPerpAmount,\\n collateralToDeposit: data.collateralToDeposit,\\n collateralToLp: data.collateralToLp,\\n amount0Min: data.amount0Min,\\n amount1Min: data.amount1Min,\\n lowerTick: data.lowerTick,\\n upperTick: data.upperTick\\n }),\\n isWethToken0\\n );\\n\\n // deposit Uni NFT token in vault\\n IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n vaultId,\\n 0,\\n _amount.add(data.collateralToWithdraw)\\n );\\n\\n // if openeded new vault, transfer vault NFT to user\\n if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n ) {\\n ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n _calldata,\\n (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n );\\n\\n IWETH9(weth).withdraw(_amount);\\n IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: data.tokenId,\\n liquidity: data.liquidity,\\n liquidityPercentage: data.liquidityPercentage,\\n amount0Min: data.amount0Min,\\n amount1Min: data.amount1Min\\n }),\\n isWethToken0\\n );\\n\\n ControllerHelperUtil.checkClosedLp(\\n _initiator,\\n controller,\\n nonfungiblePositionManager,\\n data.vaultId,\\n data.tokenId,\\n data.liquidityPercentage\\n );\\n\\n // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n _closeShortWithAmountsFromLp(\\n data.vaultId,\\n wPowerPerpAmountInLp,\\n data.wPowerPerpAmountToBurn,\\n data.collateralToWithdraw.add(data.collateralToFlashloan),\\n data.limitPriceEthPerPowerPerp,\\n data.poolFee,\\n data.burnExactRemoved\\n );\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n ) {\\n (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n _calldata,\\n (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n );\\n\\n // deposit collateral into vault and withdraw LP NFT\\n IWETH9(weth).withdraw(_amount);\\n IController(controller).deposit{value: _amount}(vaultId);\\n IController(controller).withdrawUniPositionToken(vaultId);\\n for (uint256 i; i < data.length; i++) {\\n if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n ) {\\n // increase liquidity in LP position, this can mint wPowerPerp and increase\\n ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n );\\n\\n ControllerHelperUtil.increaseLpLiquidity(\\n controller,\\n nonfungiblePositionManager,\\n wPowerPerp,\\n increaseLiquidityParam.wPowerPerpPool,\\n vaultId,\\n increaseLiquidityParam,\\n isWethToken0\\n );\\n\\n IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n ) {\\n // decrease liquidity in LP\\n ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n );\\n\\n ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: decreaseLiquidityParam.tokenId,\\n liquidity: decreaseLiquidityParam.liquidity,\\n liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n amount0Min: decreaseLiquidityParam.amount0Min,\\n amount1Min: decreaseLiquidityParam.amount1Min\\n }),\\n isWethToken0\\n );\\n\\n // if LP position is not fully closed, redeposit into vault or send back to user\\n ControllerHelperUtil.checkClosedLp(\\n _initiator,\\n controller,\\n nonfungiblePositionManager,\\n vaultId,\\n decreaseLiquidityParam.tokenId,\\n decreaseLiquidityParam.liquidityPercentage\\n );\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n ) {\\n ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.DepositIntoVaultParams)\\n );\\n\\n // make sure not to fail\\n // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n ControllerHelperUtil.mintDepositInVault(\\n controller,\\n weth,\\n vaultId,\\n depositIntoVaultParams.wPowerPerpToMint,\\n depositIntoVaultParams.collateralToDeposit\\n );\\n } else if (\\n // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n ) {\\n ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.withdrawFromVaultParams)\\n );\\n\\n uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n if (withdrawFromVaultParams.burnExactRemoved) {\\n uint256 shortAmount = _getVaultShortAmount(vaultId);\\n if (shortAmount < currentBalance) currentBalance = shortAmount;\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n vaultId,\\n currentBalance,\\n withdrawFromVaultParams.collateralToWithdraw\\n );\\n } else {\\n if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n vaultId,\\n withdrawFromVaultParams.wPowerPerpToBurn,\\n withdrawFromVaultParams.collateralToWithdraw\\n );\\n }\\n } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n // this will execute in the use case of fully closing old LP position, and creating new one\\n ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.MintAndLpParams)\\n );\\n\\n uint256 tokenId;\\n (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n controller,\\n nonfungiblePositionManager,\\n wPowerPerp,\\n weth,\\n mintAndLpParams,\\n isWethToken0\\n );\\n // deposit Uni NFT token in vault\\n IController(controller).depositUniPositionToken(vaultId, tokenId);\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n ) {\\n ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.GeneralSwapParams)\\n );\\n\\n require(\\n (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n );\\n\\n _exactInFlashSwap(\\n swapParams.tokenIn,\\n swapParams.tokenOut,\\n swapParams.poolFee,\\n swapParams.amountIn,\\n swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n \\\"\\\"\\n );\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n ) {\\n ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.CollectFeesParams)\\n );\\n\\n INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n .CollectParams({\\n tokenId: collectFeesParams.tokenId,\\n recipient: address(this),\\n amount0Max: collectFeesParams.amount0Max,\\n amount1Max: collectFeesParams.amount0Max\\n });\\n\\n INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n ) {\\n ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.DepositExistingNftParams)\\n );\\n\\n IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n }\\n }\\n\\n // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n }\\n }\\n\\n /**\\n * @notice uniswap flash swap callback function\\n * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n * @param _caller address of original function caller\\n * @param _amountToPay amount to pay back for flashswap\\n * @param _callData arbitrary data attached to callback\\n * @param _callSource identifier for which function triggered callback\\n */\\n function _swapCallback(\\n address _caller,\\n address _tokenIn,\\n address _pool,\\n uint256 _amountToPay,\\n bytes memory _callData,\\n uint8 _callSource\\n ) internal override {\\n if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n ) {\\n ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n _callData,\\n (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n );\\n\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n data.vaultId,\\n data.wPowerPerpAmountToBurn,\\n data.collateralToWithdraw\\n );\\n\\n IWETH9(weth).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n ) {\\n ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n _callData,\\n (ControllerHelperDataType.FlashSellLongWMintParams)\\n );\\n\\n if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n controller,\\n weth,\\n data.vaultId,\\n data.wPowerPerpAmountToMint,\\n data.collateralToDeposit\\n );\\n\\n // this is a newly open vault, transfer to the user\\n if (data.vaultId == 0)\\n IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n }\\n\\n IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n ) {\\n IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n ) {\\n IWETH9(weth).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n ) {\\n ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n _callData,\\n (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n );\\n\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n data.vaultId,\\n data.wPowerPerpAmountToBurn,\\n data.collateralToWithdraw\\n );\\n\\n IWETH9(weth).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n ) {\\n IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n }\\n }\\n\\n /**\\n * @notice wrap ETH to WETH\\n * @param _amount amount to wrap\\n */\\n function wrapInternal(uint256 _amount) internal {\\n if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n }\\n\\n function _closeShortWithAmountsFromLp(\\n uint256 _vaultId,\\n uint256 _wPowerPerpAmount,\\n uint256 _wPowerPerpAmountToBurn,\\n uint256 _collateralToWithdraw,\\n uint256 _limitPriceEthPerPowerPerp,\\n uint24 _poolFee,\\n bool burnExactRemoved\\n ) private {\\n if (burnExactRemoved) {\\n // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n _vaultId,\\n _wPowerPerpAmount,\\n _collateralToWithdraw\\n );\\n } else {\\n if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n // swap needed wPowerPerp amount to close short position\\n uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n _exactOutFlashSwap(\\n weth,\\n wPowerPerp,\\n _poolFee,\\n wPowerPerpDeficit,\\n _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n );\\n } else {\\n // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n _vaultId,\\n _wPowerPerpAmountToBurn,\\n _collateralToWithdraw\\n );\\n\\n uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n if (wPowerPerpExcess > 0) {\\n _exactInFlashSwap(\\n wPowerPerp,\\n weth,\\n _poolFee,\\n wPowerPerpExcess,\\n _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n \\\"\\\"\\n );\\n }\\n }\\n }\\n\\n // wrap ETH to WETH\\n wrapInternal(address(this).balance);\\n }\\n}\\n\",\"keccak256\":\"0xe9649979188ed6661ec0511b25ef05748ae61abd4ffc1f716ca7e89b7faf333e\",\"license\":\"BUSL-1.1\"},\"contracts/periphery/EulerControllerHelper.sol\":{\"content\":\"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n using SafeMath for uint256;\\n\\n address public immutable exec;\\n address public immutable euler;\\n address public immutable token;\\n address public immutable dToken;\\n\\n struct FlashloanCallbackData {\\n address caller;\\n address assetToBorrow;\\n uint256 amountToBorrow;\\n uint8 callSource;\\n bytes callData;\\n }\\n\\n constructor(\\n address _exec,\\n address _euler,\\n address _token,\\n address _dToken\\n ) {\\n exec = _exec;\\n euler = _euler;\\n token = _token;\\n dToken = _dToken;\\n }\\n\\n function _flashCallback(\\n address _initiator,\\n address _asset,\\n uint256 _amount,\\n uint8 _callSource,\\n bytes memory _calldata\\n ) internal virtual {}\\n\\n function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n // sanity checks\\n require(msg.sender == euler);\\n\\n FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n }\\n\\n /**\\n */\\n function _flashLoan(\\n address _asset,\\n uint256 _amount,\\n uint8 _callSource,\\n bytes memory _data\\n ) internal {\\n // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n IExec(exec).deferLiquidityCheck(\\n address(this),\\n abi.encode(\\n FlashloanCallbackData({\\n caller: msg.sender,\\n assetToBorrow: _asset,\\n amountToBorrow: _amount,\\n callSource: _callSource,\\n callData: _data\\n })\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x6a7f3fef2c2eca5a4851e75c632eff2e7c28b4b244ad9fb0bbe2247efe1b395c\",\"license\":\"agpl-3.0\"},\"contracts/periphery/UniswapControllerHelper.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n using Path for bytes;\\n using SafeCast for uint256;\\n using LowGasSafeMath for uint256;\\n using LowGasSafeMath for int256;\\n\\n /// @dev Uniswap factory address\\n address public immutable factory;\\n\\n struct SwapCallbackData {\\n bytes path;\\n address caller;\\n uint8 callSource;\\n bytes callData;\\n }\\n\\n /**\\n * @dev constructor\\n * @param _factory uniswap factory address\\n */\\n constructor(address _factory) {\\n require(_factory != address(0));\\n factory = _factory;\\n }\\n\\n /**\\n * @notice uniswap swap callback function for flashswap\\n * @param amount0Delta amount of token0\\n * @param amount1Delta amount of token1\\n * @param _data callback data encoded as SwapCallbackData struct\\n */\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata _data\\n ) external override {\\n require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n //ensure that callback comes from uniswap pool\\n address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n //determine the amount that needs to be repaid as part of the flashswap\\n uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n }\\n\\n /**\\n * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n * @param _tokenIn token address to sell\\n * @param _tokenOut token address to receive\\n * @param _fee pool fee\\n * @param _amountIn amount to sell\\n * @param _amountOutMinimum minimum amount to receive\\n * @param _callSource function call source\\n * @param _data arbitrary data assigned with the call\\n */\\n function _exactInFlashSwap(\\n address _tokenIn,\\n address _tokenOut,\\n uint24 _fee,\\n uint256 _amountIn,\\n uint256 _amountOutMinimum,\\n uint8 _callSource,\\n bytes memory _data\\n ) internal returns (uint256) {\\n //calls internal uniswap swap function that will trigger a callback for the flash swap\\n uint256 amountOut = _exactInputInternal(\\n _amountIn,\\n address(this),\\n uint160(0),\\n SwapCallbackData({\\n path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n caller: msg.sender,\\n callSource: _callSource,\\n callData: _data\\n })\\n );\\n\\n //slippage limit check\\n require(amountOut >= _amountOutMinimum);\\n\\n return amountOut;\\n }\\n\\n /**\\n * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n * @param _tokenIn token address to sell\\n * @param _tokenOut token address to receive\\n * @param _fee pool fee\\n * @param _amountOut exact amount to receive\\n * @param _amountInMaximum maximum amount to sell\\n * @param _callSource function call source\\n * @param _data arbitrary data assigned with the call\\n */\\n function _exactOutFlashSwap(\\n address _tokenIn,\\n address _tokenOut,\\n uint24 _fee,\\n uint256 _amountOut,\\n uint256 _amountInMaximum,\\n uint8 _callSource,\\n bytes memory _data\\n ) internal {\\n //calls internal uniswap swap function that will trigger a callback for the flash swap\\n uint256 amountIn = _exactOutputInternal(\\n _amountOut,\\n address(this),\\n uint160(0),\\n SwapCallbackData({\\n path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n caller: msg.sender,\\n callSource: _callSource,\\n callData: _data\\n })\\n );\\n\\n //slippage limit check\\n require(amountIn <= _amountInMaximum);\\n }\\n\\n /**\\n * @notice function to be called by uniswap callback.\\n * @dev this function should be overridden by the child contract\\n * param _caller initial strategy function caller\\n * param _tokenIn token address sold\\n * param _tokenOut token address bought\\n * param _fee pool fee\\n * param _amountToPay amount to pay for the pool second token\\n * param _callData arbitrary data assigned with the flashswap call\\n * param _callSource function call source\\n */\\n function _swapCallback(\\n address _caller,\\n address _tokenIn,\\n address _pool,\\n uint256 _amountToPay,\\n bytes memory _callData,\\n uint8 _callSource\\n ) internal virtual {}\\n\\n /**\\n * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n * @param _amountIn amount of token to pay\\n * @param _recipient recipient for receive\\n * @param _sqrtPriceLimitX96 price limit\\n * @return amount of token bought (amountOut)\\n */\\n function _exactInputInternal(\\n uint256 _amountIn,\\n address _recipient,\\n uint160 _sqrtPriceLimitX96,\\n SwapCallbackData memory data\\n ) private returns (uint256) {\\n (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n //uniswap token0 has a lower address than token1\\n //if tokenIn0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n uint256 amount0Min; // minimum amount of token0 to LP\\n uint256 amount1Min; // minimum amount of token1 to LP\\n int24 lowerTick; // range lower tick to LP in\\n int24 upperTick; // range upper tick to LP in\\n }\\n\\n /// @dev params for flashloanCloseVaultLpNft()\\n struct FlashloanCloseVaultLpNftParam {\\n uint256 vaultId; // vault ID\\n uint256 tokenId; // Uni NFT token ID\\n uint256 liquidity; // amount of liquidity in LP position\\n uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n uint256 collateralToWithdraw; // amount of ETH to withdraw\\n uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n uint24 poolFee; // uniswap pool fee\\n bool burnExactRemoved; // flag to set burning exact amount removed from LP or the current contract balance\\n }\\n\\n /// @dev params for _closeUniLp() \\n struct CloseUniLpParams {\\n uint256 tokenId; // Uni v3 NFT id\\n uint256 liquidity; // LP liquidity amount\\n uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n }\\n\\n /// @dev params for sellAll()\\n struct ReduceLiquidityAndSellParams {\\n uint256 tokenId; // Uni token ID\\n uint256 liquidity; // LP liquidity amount\\n uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n }\\n\\n /// @dev params for rebalanceLpWithoutVault()\\n struct RebalanceLpWithoutVaultParams {\\n address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n uint256 tokenId; // Uni token ID\\n uint256 liquidity; // LP liquidity amount\\n uint256 wPowerPerpAmountDesired; // wPowerPerp amount to LP\\n uint256 wethAmountDesired; // WETH amount to LP\\n uint256 amount0DesiredMin; // amount min to get when LPing for asset0\\n uint256 amount1DesiredMin; // amount min to get when LPing for asset1\\n uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n uint256 amount0Min; // amount min to get when closing LP for asset0\\n uint256 amount1Min; // amount min to get when closing LP for asset1\\n int24 lowerTick; // LP lower tick\\n int24 upperTick; // LP upper tick\\n uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n }\\n\\n /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n struct LpWPowerPerpPoolParams {\\n address recipient; // recipient address\\n uint256 amount0Desired; // amount desired to LP for asset0\\n uint256 amount1Desired; // amount desired to LP for asset1\\n uint256 amount0Min; // amount min to LP for asset0\\n uint256 amount1Min; // amount min to LP for asset1\\n int24 lowerTick; // LP lower tick\\n int24 upperTick; // LP upper tick\\n }\\n\\n /// @dev params for rebalanceLpInVault()\\n struct RebalanceLpInVaultParams {\\n RebalanceVaultNftType rebalanceLpInVaultType;\\n bytes data;\\n }\\n\\n /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n struct IncreaseLpLiquidityParams {\\n address wPowerPerpPool; // Uni v3 pool address to increase liquidity in\\n uint256 tokenId; // Uni v3 NFT token id\\n uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n uint256 collateralToDeposit; // collateral to deposit into vault\\n uint256 wethAmountToLp; // WETH amount to LP\\n uint256 amount0Min; // amount min to get for LPing of asset0\\n uint256 amount1Min; // amount min to get for LPing of asset1\\n }\\n\\n /// @dev struct for decrease liquidity in LP position\\n struct DecreaseLpLiquidityParams { \\n uint256 tokenId; // Uni v3 NFT token id\\n uint256 liquidity; // LP liquidity amount\\n uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n uint128 amount0Min; // amount min to get for LPing of asset0\\n uint128 amount1Min; // amount min to get for LPing of asset1\\n }\\n\\n /// @dev struct for minting into vault\\n struct DepositIntoVaultParams {\\n uint256 wPowerPerpToMint; // wPowerPerp amount to mint\\n uint256 collateralToDeposit; // collateral amount to deposit\\n }\\n\\n /// @dev struct for withdrawing from vault\\n struct withdrawFromVaultParams { \\n uint256 wPowerPerpToBurn; // wPowerPerp amount to burn\\n uint256 collateralToWithdraw; // collateral to withdraw\\n bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n }\\n\\n /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n struct GeneralSwapParams {\\n address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n uint256 amountIn; // amount to swap in\\n uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n }\\n\\n /// @dev struct for collecting fees owed from a uniswap NFT\\n struct CollectFeesParams {\\n uint256 tokenId;\\n uint128 amount0Max;\\n uint128 amount1Max;\\n }\\n\\n /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n struct DepositExistingNftParams {\\n uint256 tokenId; // Uni v3 NFT id\\n }\\n}\",\"keccak256\":\"0x04a47d47c3e0a1ec4e834f9aa466960200084fbdee47f0f513990b2c4708b02a\",\"license\":\"BUSL-1.1\"},\"contracts/periphery/lib/ControllerHelperUtil.sol\":{\"content\":\"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n using SafeMath for uint256;\\n using Address for address payable;\\n\\n /**\\n * @notice fully or partially close Uni v3 LP\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n * @return withdrawn wPowerPerp and WETH amounts\\n */\\n function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n .DecreaseLiquidityParams({\\n tokenId: _params.tokenId,\\n liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n amount0Min: _params.amount0Min,\\n amount1Min: _params.amount1Min,\\n deadline: block.timestamp\\n });\\n INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n uint256 wethAmount;\\n uint256 _wPowerPerpAmount;\\n (_isWethToken0)\\n ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n INonfungiblePositionManager.CollectParams({\\n tokenId: _params.tokenId,\\n recipient: address(this),\\n amount0Max: type(uint128).max,\\n amount1Max: type(uint128).max\\n })\\n )\\n : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n INonfungiblePositionManager.CollectParams({\\n tokenId: _params.tokenId,\\n recipient: address(this),\\n amount0Max: type(uint128).max,\\n amount1Max: type(uint128).max\\n })\\n );\\n\\n return (_wPowerPerpAmount, wethAmount);\\n }\\n\\n /**\\n * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n * @param _collateralToLp amount of ETH collateral to LP\\n * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n * @param _lowerTick LP position lower tick\\n * @param _upperTick LP position upper tick\\n * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n * @return exact amount0 and amount1 to be LPed\\n */\\n function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n uint256 amount0Desired; \\n uint256 amount1Desired;\\n\\n {\\n (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n }\\n \\n return (amount0Desired, amount1Desired);\\n }\\n\\n /**\\n * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n * @param _controller wPowerPerp controller address\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n * @return _vaultId and tokenId\\n */\\n function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n \\n uint256 _vaultId = _mintAndLpParams.vaultId;\\n uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n _mintAndLpParams.vaultId,\\n amountToMint,\\n 0\\n );\\n }\\n // LP amount0Desired and amount1Desired in Uni v3\\n uint256 uniTokenId = lpWPowerPerpPool(\\n _nonfungiblePositionManager,\\n _mintAndLpParams.wPowerPerpPool,\\n ControllerHelperDataType.LpWPowerPerpPoolParams({\\n recipient: _mintAndLpParams.recipient,\\n amount0Desired: amount0Desired,\\n amount1Desired: amount1Desired,\\n amount0Min: _mintAndLpParams.amount0Min,\\n amount1Min: _mintAndLpParams.amount1Min,\\n lowerTick: _mintAndLpParams.lowerTick,\\n upperTick: _mintAndLpParams.upperTick\\n })\\n );\\n return (_vaultId, uniTokenId);\\n }\\n\\n /**\\n * @notice increase liquidityin Uni v3 position\\n * @param _controller controller address\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _vaultId vault Id\\n * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n */\\n function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n (\\n ,\\n ,\\n ,\\n ,\\n ,\\n int24 tickLower,\\n int24 tickUpper,\\n ,\\n ,\\n ,\\n ,\\n \\n ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n _vaultId,\\n _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n 0\\n );\\n }\\n }\\n\\n INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n tokenId: _increaseLiquidityParam.tokenId,\\n amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n amount0Min: _increaseLiquidityParam.amount0Min,\\n amount1Min: _increaseLiquidityParam.amount1Min,\\n deadline: block.timestamp\\n });\\n\\n INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n }\\n\\n /**\\n * @notice mint wPowerPerp in vault\\n * @param _controller controller address\\n * @param _weth WETH address\\n * @param _vaultId vault Id\\n * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n * @param _collateralToDeposit amount of collateral to deposit\\n */\\n function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n uint256 vaultId = _vaultId;\\n if (_wPowerPerpToMint > 0) {\\n vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n _vaultId,\\n _wPowerPerpToMint,\\n 0\\n );\\n } else {\\n IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n }\\n return vaultId;\\n }\\n\\n /**\\n * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n * @param _controller controller address\\n * @param _weth weth address\\n * @param _vaultId vault Id\\n * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n * @param _collateralToWithdraw amount of collateral to withdraw\\n */\\n function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n IController(_controller).burnWPowerPerpAmount(\\n _vaultId,\\n _wPowerPerpToBurn,\\n _collateralToWithdraw\\n );\\n\\n if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n }\\n\\n /**\\n * @notice LP into Uniswap V3 pool\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n */\\n function lpWPowerPerpPool(\\n address _nonfungiblePositionManager,\\n address _wPowerPerpPool,\\n ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n ) public returns (uint256) {\\n INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n tickLower: int24(_params.lowerTick),\\n tickUpper: int24(_params.upperTick),\\n amount0Desired: _params.amount0Desired,\\n amount1Desired: _params.amount1Desired,\\n amount0Min: _params.amount0Min,\\n amount1Min: _params.amount1Min,\\n recipient: _params.recipient,\\n deadline: block.timestamp\\n });\\n (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n mintParams\\n );\\n return tokenId;\\n }\\n\\n /**\\n * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n * @param _user user address\\n * @param _controller controller address\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _vaultId vault ID\\n * @param _tokenId Uni LP NFT id\\n * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n */\\n function checkClosedLp(\\n address _user,\\n address _controller,\\n address _nonfungiblePositionManager,\\n uint256 _vaultId,\\n uint256 _tokenId,\\n uint256 _liquidityPercentage\\n ) public {\\n if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n address(this),\\n _user,\\n _tokenId\\n );\\n } else {\\n IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n }\\n }\\n\\n /**\\n * @notice send ETH and wPowerPerp\\n * @param _weth WETH address\\n * @param _wPowerPerp wPowerPerp address\\n */\\n function sendBack(address _weth, address _wPowerPerp) public {\\n IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n payable(msg.sender).sendValue(address(this).balance);\\n uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n if (wPowerPerpBalance > 0) {\\n IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n }\\n }\\n}\",\"keccak256\":\"0x51c6185083d747a36ee8543219c0e7a326b866c0bdc113e82956cd4e226f7ba3\",\"license\":\"BUSL-1.1\"},\"contracts/periphery/lib/LiquidityAmounts.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n /// @notice Downcasts uint256 to uint128\\n /// @param x The uint258 to be downcasted\\n /// @return y The passed value, downcasted to uint128\\n function toUint128(uint256 x) private pure returns (uint128 y) {\\n require((y = uint128(x)) == x);\\n }\\n\\n /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param amount0 The amount0 being sent in\\n /// @return liquidity The amount of returned liquidity\\n function getLiquidityForAmount0(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint256 amount0\\n ) internal pure returns (uint128 liquidity) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n }\\n\\n /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param amount1 The amount1 being sent in\\n /// @return liquidity The amount of returned liquidity\\n function getLiquidityForAmount1(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint256 amount1\\n ) internal pure returns (uint128 liquidity) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n }\\n\\n /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n /// pool prices and the prices at the tick boundaries\\n /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param amount0 The amount of token0 being sent in\\n /// @param amount1 The amount of token1 being sent in\\n /// @return liquidity The maximum amount of liquidity received\\n function getLiquidityForAmounts(\\n uint160 sqrtRatioX96,\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint256 amount0,\\n uint256 amount1\\n ) internal pure returns (uint128 liquidity) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n if (sqrtRatioX96 <= sqrtRatioAX96) {\\n liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n } else {\\n liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n }\\n }\\n\\n /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param liquidity The liquidity being valued\\n /// @return amount0 The amount of token0\\n function getAmount0ForLiquidity(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity\\n ) internal pure returns (uint256 amount0) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n return\\n FullMath.mulDiv(\\n uint256(liquidity) << FixedPoint96.RESOLUTION,\\n sqrtRatioBX96 - sqrtRatioAX96,\\n sqrtRatioBX96\\n ) / sqrtRatioAX96;\\n }\\n\\n /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param liquidity The liquidity being valued\\n /// @return amount1 The amount of token1\\n function getAmount1ForLiquidity(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity\\n ) internal pure returns (uint256 amount1) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n }\\n\\n /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n /// pool prices and the prices at the tick boundaries\\n /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param liquidity The liquidity being valued\\n /// @return amount0 The amount of token0\\n /// @return amount1 The amount of token1\\n function getAmountsForLiquidity(\\n uint160 sqrtRatioX96,\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity\\n ) internal pure returns (uint256 amount0, uint256 amount1) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n if (sqrtRatioX96 <= sqrtRatioAX96) {\\n amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n } else {\\n amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n }\\n }\\n\\n function getAmountsFromLiquidity( \\n uint160 sqrtRatioX96,\\n int24 currentTick,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity\\n ) internal pure returns (uint256 amount0, uint256 amount1) {\\n if (currentTick < tickLower) {\\n amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n TickMath.getSqrtRatioAtTick(tickLower),\\n TickMath.getSqrtRatioAtTick(tickUpper),\\n liquidity,\\n false\\n );\\n } else if (currentTick < tickUpper) {\\n amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n sqrtRatioX96,\\n TickMath.getSqrtRatioAtTick(tickUpper),\\n liquidity,\\n false\\n );\\n amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n TickMath.getSqrtRatioAtTick(tickLower),\\n sqrtRatioX96,\\n liquidity,\\n false\\n );\\n } else {\\n amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n TickMath.getSqrtRatioAtTick(tickLower),\\n TickMath.getSqrtRatioAtTick(tickUpper),\\n liquidity,\\n false\\n );\\n }\\n \\n }\\n\\n}\\n\",\"keccak256\":\"0xb4b0f464529a43f3ca7a9d6afc5976902c0a004649bdf3239ca77469d26b7cf2\",\"license\":\"GPL-2.0-or-later\"}},\"version\":1}", + "bytecode": "0x6101e06040523480156200001257600080fd5b5060405162006a3e38038062006a3e833981016040819052620000359162000679565b8282876001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200007157600080fd5b505afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac919062000655565b83876001600160a01b038116620000c257600080fd5b6001600160601b0319606091821b811660805294811b851660a05292831b841660c05290821b831660e052811b82166101005287901b166101405260408051634ea64a2160e11b815290516001600160a01b03881691639d4c9442916004808301926020929190829003018186803b1580156200013e57600080fd5b505afa15801562000153573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000179919062000655565b6001600160a01b0316610160816001600160a01b031660601b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b158015620001d057600080fd5b505afa158015620001e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020b919062000655565b6001600160a01b0316610180816001600160a01b031660601b81525050856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200026257600080fd5b505afa15801562000277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029d919062000655565b6001600160601b0319606091821b81166101a0529086901b166101c052604080516307f07b1360e41b815290516001600160a01b03881691637f07b130916004808301926020929190829003018186803b158015620002fb57600080fd5b505afa15801562000310573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000336919062000655565b6001600160a01b0316866001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200037957600080fd5b505afa1580156200038e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003b4919062000655565b6001600160a01b031610151561012081151560f81b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200040757600080fd5b505afa1580156200041c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000442919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200047392919062000736565b602060405180830381600087803b1580156200048e57600080fd5b505af1158015620004a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c99190620006f9565b50856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200050457600080fd5b505afa15801562000519573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200053f919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200057092919062000736565b602060405180830381600087803b1580156200058b57600080fd5b505af1158015620005a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c69190620006f9565b5060405163a22cb46560e01b81526001600160a01b0386169063a22cb46590620005f89089906001906004016200071b565b600060405180830381600087803b1580156200061357600080fd5b505af115801562000628573d6000803e3d6000fd5b505050505050505050506200074f565b80516001600160a01b03811681146200065057600080fd5b919050565b60006020828403121562000667578081fd5b620006728262000638565b9392505050565b60008060008060008060c0878903121562000692578182fd5b6200069d8762000638565b9550620006ad6020880162000638565b9450620006bd6040880162000638565b9350620006cd6060880162000638565b9250620006dd6080880162000638565b9150620006ed60a0880162000638565b90509295509295509295565b6000602082840312156200070b578081fd5b8151801515811462000672578182fd5b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160f81c6101405160601c6101605160601c6101805160601c6101a05160601c6101c05160601c615fe162000a5d600039806102f452806103dc52806104cd52806108aa5280610b315280610cca5280610efc5280610f8652806110f1528061183f52806118d55280611a4152806120bc52806125eb528061274a5280612a5f5280612bff5280612d5552806132cb528061367e52508061074952806108275280610a385280610acf5280610bef5280610d0e5280610e67528061118252806111fc528061125e52806112c4528061136652806113d3528061177a5280611c0552806120fe52806122f5528061246852806128405280612e0b5280612f13528061310852806131d0528061330d528061349b528061355b528061384d528061392552806139a45280613a6a5280613b0b5280613c405280613cad5280613df5528061404e528061411d52508061076a52806108065280610a5a5280610c115280610cec5280610e895280611161528061121e52806112e652806113f452806116ae528061175952806120dd5280612a815280612ff352806132ec52806134db528061351b52806139c55280613aea5280613f165280613f86525080610dcc5280611e7252806123a25280613e915250806104ab5280610ca852806110cf5280611a1f528061209b528061224f52806122d452806124e65280612565528061272852806128bc528061293b5280612a3d5280612b145280612d335280612ef152806130e652806131ae52806132aa52806133da5280613789528061382b52806139035280613a485280613c1e5280613dd352806140fb52806144985250806103ff528061053d52806105b852806106a852806108f252806109245280610d32528061100d528061195e52806121a4528061265b5280612aa85280612c6d528061332f5250806114b052806116195280611aea525080611bdb52508061146c52806115695280611b0e5250806117d85280611f145250806117fc5280611b7752806147505250615fe16000f3fe6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b81526000935073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b815290915073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f0000000000000000000000000000000000000000000000000000000000000000156106515773B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b73B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b73B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b815260009073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b50505050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b815291925073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b815290915073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b905060008073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b5050505073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b50505050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b815291925073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b905073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b9050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b815260009373B53c2eE92A24B08521912e1687Bc8142a7E6a9EE93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033", + "deployedBytecode": "0x6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b81526000935073__$561e80098325da493156966792c25e3551$__925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f0000000000000000000000000000000000000000000000000000000000000000156106515773__$561e80098325da493156966792c25e3551$__63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b73__$561e80098325da493156966792c25e3551$__63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b73__$561e80098325da493156966792c25e3551$__63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b815260009073__$561e80098325da493156966792c25e3551$__90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b815291925073__$561e80098325da493156966792c25e3551$__9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b905060008073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b5050505073__$561e80098325da493156966792c25e3551$__6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b815293945073__$561e80098325da493156966792c25e3551$__9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b815291925073__$561e80098325da493156966792c25e3551$__91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b905073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b815273__$561e80098325da493156966792c25e3551$__9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b815273__$561e80098325da493156966792c25e3551$__92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b9050600073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b815260009373__$561e80098325da493156966792c25e3551$__93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033", + "libraries": { + "ControllerHelperUtil": "0xB53c2eE92A24B08521912e1687Bc8142a7E6a9EE" + }, + "devdoc": { + "kind": "dev", + "methods": { + "closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))": { + "details": "user should approve this contract for Uni NFT transfer", + "params": { + "_params": "ControllerHelperDataType.CloseShortWithUserNftParams struct" + } + }, + "flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))": { + "details": "sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan", + "params": { + "_params": "ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct" + } + }, + "flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))": { + "details": "flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp", + "params": { + "_params": "ControllerHelperDataType.FlashSellLongWMintParams struct" + } + }, + "flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))": { + "details": "this function", + "params": { + "_params": "ControllerHelperDataType.FlashswapWBurnBuyLongParams struct" + } + }, + "onERC721Received(address,address,uint256,bytes)": { + "details": "accept erc721 from safeTransferFrom and safeMint after callback", + "returns": { + "_0": "returns received selector" + } + }, + "rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])": { + "params": { + "_collateralToFlashloan": "collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT", + "_params": "array of ControllerHelperDataType.RebalanceLpInVaultParams structs", + "_vaultId": "vault ID" + } + }, + "rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))": { + "params": { + "_params": "ControllerHelperDataType.RebalanceLpWithoutVaultParams struct" + } + }, + "reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))": { + "params": { + "_params": "ControllerHelperDataType.ReduceLiquidityAndSellParams struct" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "params": { + "_data": "callback data encoded as SwapCallbackData struct", + "amount0Delta": "amount of token0", + "amount1Delta": "amount of token1" + } + }, + "wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))": { + "params": { + "_params": "ControllerHelperDataType.MintAndLpParams struct" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))": { + "notice": "close short position with user Uniswap v3 LP NFT" + }, + "flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))": { + "notice": "FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan" + }, + "flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))": { + "notice": "sell long wPowerPerp and flashswap mint short position" + }, + "flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))": { + "notice": "flash close position and buy long squeeth" + }, + "rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])": { + "notice": "Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault" + }, + "rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))": { + "notice": "Rebalance LP nft through trading" + }, + "reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))": { + "notice": "sell all LP wPowerPerp amounts to WETH and send back to user" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "uniswap swap callback function for flashswap" + }, + "wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))": { + "notice": "mint WPowerPerp and LP into Uniswap v3 pool" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/packages/frontend/src/constants/address.ts b/packages/frontend/src/constants/address.ts index 299d43bb1..ce697a25e 100644 --- a/packages/frontend/src/constants/address.ts +++ b/packages/frontend/src/constants/address.ts @@ -124,3 +124,10 @@ export const CRAB_STRATEGY2: Address = { } export const ZERO_ADDR = '0x0000000000000000000000000000000000000000' + +export const CONTROLLER_HELPER: Address = { + 1: '0xfa86d43b41Fa7a759c606130cc81970A955ff816', + 3: '', + 421611: '', + 31337: '', +} diff --git a/packages/frontend/src/state/positions/atoms.ts b/packages/frontend/src/state/positions/atoms.ts index 047c66ddf..9ce484913 100644 --- a/packages/frontend/src/state/positions/atoms.ts +++ b/packages/frontend/src/state/positions/atoms.ts @@ -19,6 +19,7 @@ import { CRAB_STRATEGY, CRAB_MIGRATION, CRAB_STRATEGY2, + CONTROLLER_HELPER, } from '@constants/address' import { networkIdAtom, web3Atom } from '../wallet/atoms' import { BIG_ZERO } from '@constants/index' @@ -56,6 +57,7 @@ export const addressesAtom = atom((get) => { crabStrategy: CRAB_STRATEGY[networkId].toLowerCase(), crabMigration: CRAB_MIGRATION[networkId].toLowerCase(), crabStrategy2: CRAB_STRATEGY2[networkId].toLowerCase(), + controllerHelper: CONTROLLER_HELPER[networkId].toLowerCase(), } }) From 5f50ed737654e624f52a379cd5cd8a5d24da4534 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 14 Jun 2022 23:32:08 -0700 Subject: [PATCH 02/82] open position hook --- .../frontend/src/state/contracts/atoms.ts | 8 ++ packages/frontend/src/state/lp/atoms.ts | 17 ++++ packages/frontend/src/state/lp/hooks.ts | 87 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 packages/frontend/src/state/lp/atoms.ts create mode 100644 packages/frontend/src/state/lp/hooks.ts diff --git a/packages/frontend/src/state/contracts/atoms.ts b/packages/frontend/src/state/contracts/atoms.ts index 21bbf4918..2a752f666 100644 --- a/packages/frontend/src/state/contracts/atoms.ts +++ b/packages/frontend/src/state/contracts/atoms.ts @@ -3,6 +3,7 @@ import { Contract } from 'web3-eth-contract' import { getContract } from '@utils/getContract' import controllerAbi from '../../abis/controller.json' +import controllerHelperAbi from '../../abis/controllerHelper.json' import crabStrategyAbi from '../../abis/crabStrategy.json' import crabStrategyV2Abi from '../../abis/crabStrategyV2.json' import positionManagerAbi from '../../abis/NFTpositionmanager.json' @@ -75,3 +76,10 @@ export const crabMigrationContractAtom = atom((get) => { if (!web3) return null return getContract(web3, crabMigration, crabMigrationAbi) }) + +export const controllerHelperHelperContractAtom = atom((get) => { + const web3 = get(web3Atom) + const { controllerHelper } = get(addressesAtom) + if (!web3) return null + return getContract(web3, controllerHelper, controllerHelperAbi) +}) diff --git a/packages/frontend/src/state/lp/atoms.ts b/packages/frontend/src/state/lp/atoms.ts new file mode 100644 index 000000000..2b94ac0fe --- /dev/null +++ b/packages/frontend/src/state/lp/atoms.ts @@ -0,0 +1,17 @@ +import { atom } from 'jotai' +import { BIG_ZERO } from '@constants/index' + +export const ethCollateralPnlAtom = atom(BIG_ZERO) +export const shortUnrealizedPNLAtom = atom({ usd: BIG_ZERO, eth: BIG_ZERO, loading: true }) +export const longUnrealizedPNLAtom = atom({ usd: BIG_ZERO, eth: BIG_ZERO, loading: true }) +export const buyQuoteAtom = atom(BIG_ZERO) +export const sellQuoteAtom = atom({ + amountOut: BIG_ZERO, + minimumAmountOut: BIG_ZERO, + priceImpact: '0', + pools: Array>(), +}) + +export const longGainAtom = atom(BIG_ZERO) +export const shortGainAtom = atom(BIG_ZERO) +export const loadingAtom = atom(true) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts new file mode 100644 index 000000000..bc8894cb4 --- /dev/null +++ b/packages/frontend/src/state/lp/hooks.ts @@ -0,0 +1,87 @@ +import { tickToPrice } from '@uniswap/v3-sdk' + +import { fromTokenAmount } from '@utils/calculations' +import { useAtomValue } from 'jotai' +import { addressesAtom, isWethToken0Atom } from '../positions/atoms' +import BigNumber from 'bignumber.js' +import { BIG_ZERO, OSQUEETH_DECIMALS } from '@constants/index' +import { controllerHelperHelperContractAtom } from '../contracts/atoms' +import useAppCallback from '@hooks/useAppCallback' +import { addressAtom } from '../wallet/atoms' +import { normFactorAtom } from '../controller/atoms' +import { Price, Token } from '@uniswap/sdk-core' +import JSBI from 'jsbi' +import { useHandleTransaction } from '../wallet/hooks' +const PRICE_FIXED_DIGITS = 8 + +// Opening a mint and LP position +export const useOpenPosition = () => { + const { squeethPool } = useAtomValue(addressesAtom) + const normalizationFactor = useAtomValue(normFactorAtom) + const address = useAtomValue(addressAtom) + const contract = useAtomValue(controllerHelperHelperContractAtom) + const handleTransaction = useHandleTransaction() + const openPosition = useAppCallback( + async ( + ethAmount: BigNumber, + squeethToMint: BigNumber, + collateralAmount: BigNumber, + vaultId: BigNumber, + lowerTickInput: number, + upperTickInput: number, + onTxConfirmed?: () => void, + ) => { + const amount0Min = BIG_ZERO + const amount1Min = BIG_ZERO + const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS).multipliedBy(normalizationFactor) + + // Closest 60 tick width above or below current tick (60 is minimum tick width for 30bps pool) + + // Closest valid lower tick + const lowerTickBelow = lowerTickInput - (lowerTickInput % 60) + const lowerTickAbove = lowerTickInput + (lowerTickInput % 60) + const lowerTick = + Math.abs(lowerTickAbove - lowerTickInput) < Math.abs(lowerTickBelow - lowerTickInput) + ? lowerTickAbove + : lowerTickBelow + + // Closest valid upper tick + const upperTickBelow = upperTickInput - (upperTickInput % 60) + const upperTickAbove = upperTickInput + (upperTickInput % 60) + const upperTick = + Math.abs(upperTickAbove - upperTickInput) < Math.abs(upperTickBelow - upperTickInput) + ? upperTickAbove + : upperTickBelow + + const params = { + recipient: address, + wPowerPerpPool: squeethPool, + vaultId: vaultId, + wPowerPerpAmount: mintWSqueethAmount, + collateralToDeposit: collateralAmount, + collateralToLp: BIG_ZERO, + amount0Min: amount0Min, + amount1Min: amount1Min, + lowerTick: lowerTick, + upperTick: upperTick, + } + + return handleTransaction( + contract!.methods.wMintLp(params, { value: collateralAmount }).send({ + from: address, + value: fromTokenAmount(ethAmount, 18), + }), + onTxConfirmed, + ) + }, + [], + ) + return openPosition +} + +export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: number): Price | undefined { + if (!baseToken || !quoteToken || typeof tick !== 'number') { + return undefined + } + return tickToPrice(baseToken, quoteToken, tick) +} From e18bc67f1650dc736578b886f8b7c65816ac7ff3 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 15 Jun 2022 00:40:32 -0700 Subject: [PATCH 03/82] drafting close position --- packages/frontend/src/state/lp/hooks.ts | 62 ++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index bc8894cb4..bbf326813 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -1,18 +1,66 @@ import { tickToPrice } from '@uniswap/v3-sdk' import { fromTokenAmount } from '@utils/calculations' -import { useAtomValue } from 'jotai' -import { addressesAtom, isWethToken0Atom } from '../positions/atoms' +import { useAtom, useAtomValue } from 'jotai' +import { addressesAtom } from '../positions/atoms' import BigNumber from 'bignumber.js' import { BIG_ZERO, OSQUEETH_DECIMALS } from '@constants/index' -import { controllerHelperHelperContractAtom } from '../contracts/atoms' +import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom } from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' import { addressAtom } from '../wallet/atoms' import { normFactorAtom } from '../controller/atoms' import { Price, Token } from '@uniswap/sdk-core' -import JSBI from 'jsbi' import { useHandleTransaction } from '../wallet/hooks' -const PRICE_FIXED_DIGITS = 8 +import { squeethPriceeAtom, wethPriceAtom } from '../squeethPool/atoms' + +// Close position with flashloan +export const useClosePosition = () => { + const address = useAtomValue(addressAtom) + const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) + const { controllerHelper } = useAtomValue(addressesAtom) + const controllerContract = useAtomValue(controllerContractAtom) + const handleTransaction = useHandleTransaction() + const squeethPrice = useAtomValue(squeethPriceeAtom) + const ethPrice = useAtomValue(wethPriceAtom) + const positionManager = useAtomValue(nftManagerContractAtom) + const closePosition = useAppCallback(async (vaultId: BigNumber, onTxConfirmed?: () => void) => { + if (!controllerContract || !controllerHelperContract || !address || !positionManager) return + const one = new BigNumber(10).pow(18) + const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId + const vaultBefore = await controllerContract?.methods.vaults(vaultId) + const scaledEthPrice = ethPrice.div(10000) + const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one) + const collateralToFlashloan = debtInEth.mul(3).div(2).add(0.01) + const slippage = new BigNumber(3).multipliedBy(new BigNumber(10).pow(16)) + const limitPriceEthPerPowerPerp = squeethPrice.multipliedBy(one.minus(slippage)).div(one) + const positionBefore = await positionManager.methods.positions(uniTokenId) + + const flashloanCloseVaultLpNftParam = { + vaultId: vaultId, + tokenId: uniTokenId, + liquidity: positionBefore.liquidity, + liquidityPercentage: 1, + wPowerPerpAmountToBurn: vaultBefore.shortAmount.toString(), + collateralToFlashloan: collateralToFlashloan.toString(), + collateralToWithdraw: 0, + limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp.toString(), + amount0Min: 0, + amount1Min: 0, + poolFee: 3000, + burnExactRemoved: false, + } + + await controllerContract.methods.updateOperator(vaultId, controllerHelper) + + return handleTransaction( + await controllerHelperContract.methods.flashloanCloseVaultLpNft(flashloanCloseVaultLpNftParam).send({ + from: address, + }), + onTxConfirmed, + ) + }, []) + return closePosition +} // Opening a mint and LP position export const useOpenPosition = () => { @@ -66,8 +114,10 @@ export const useOpenPosition = () => { upperTick: upperTick, } + if (!contract || !address) return null + return handleTransaction( - contract!.methods.wMintLp(params, { value: collateralAmount }).send({ + contract.methods.wMintLp(params, { value: collateralAmount }).send({ from: address, value: fromTokenAmount(ethAmount, 18), }), From 25ea441622e8423abce48ee4ace67e6e79b64da1 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 15 Jun 2022 13:18:57 -0700 Subject: [PATCH 04/82] collect fees hook --- packages/frontend/src/state/lp/hooks.ts | 44 +++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index bbf326813..eac4ad9d7 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -12,6 +12,7 @@ import { normFactorAtom } from '../controller/atoms' import { Price, Token } from '@uniswap/sdk-core' import { useHandleTransaction } from '../wallet/hooks' import { squeethPriceeAtom, wethPriceAtom } from '../squeethPool/atoms' +import ethers from 'ethers' // Close position with flashloan export const useClosePosition = () => { @@ -93,6 +94,7 @@ export const useOpenPosition = () => { ? lowerTickAbove : lowerTickBelow + // TODO: ensure we're not hitting a bound for a tick // Closest valid upper tick const upperTickBelow = upperTickInput - (upperTickInput % 60) const upperTickAbove = upperTickInput + (upperTickInput % 60) @@ -129,6 +131,48 @@ export const useOpenPosition = () => { return openPosition } +// Collect fees +export const useCollectFees = () => { + const address = useAtomValue(addressAtom) + const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) + const { controllerHelper } = useAtomValue(addressesAtom) + const controllerContract = useAtomValue(controllerContractAtom) + const handleTransaction = useHandleTransaction() + const ethPrice = useAtomValue(wethPriceAtom) + const positionManager = useAtomValue(nftManagerContractAtom) + const collectFees = useAppCallback(async (vaultId: BigNumber, onTxConfirmed?: () => void) => { + if (!controllerContract || !controllerHelperContract || !address || !positionManager) return + const one = new BigNumber(10).pow(18) + const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId + const vaultBefore = await controllerContract?.methods.vaults(vaultId) + const scaledEthPrice = ethPrice.div(10000) + const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one) + const collateralToFlashloan = debtInEth.mul(3).div(2).add(0.01) + const amount0Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1) + const amount1Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1) + + const abiCoder = new ethers.utils.AbiCoder() + const rebalanceLpInVaultParams = [ + { + rebalanceLpInVaultType: new BigNumber(6), + // CollectFees + data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [uniTokenId, amount0Max, amount1Max]), + }, + ] + + await controllerContract.methods.updateOperator(vaultId, controllerHelper) + return handleTransaction( + await controllerHelperContract.methods + .rebalanceLpInVault(vaultId, collateralToFlashloan, rebalanceLpInVaultParams) + .send({ + from: address, + }), + onTxConfirmed, + ) + }, []) + return collectFees +} + export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: number): Price | undefined { if (!baseToken || !quoteToken || typeof tick !== 'number') { return undefined From 7ffd9f9faf9fe91d9107a96591eb77978ef4ed3b Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 15 Jun 2022 16:15:37 -0700 Subject: [PATCH 05/82] rebalance via general swap --- packages/frontend/src/state/lp/hooks.ts | 150 +++++++++++++++++++++--- 1 file changed, 133 insertions(+), 17 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index eac4ad9d7..22a4daeeb 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -2,7 +2,7 @@ import { tickToPrice } from '@uniswap/v3-sdk' import { fromTokenAmount } from '@utils/calculations' import { useAtom, useAtomValue } from 'jotai' -import { addressesAtom } from '../positions/atoms' +import { addressesAtom, isWethToken0Atom } from '../positions/atoms' import BigNumber from 'bignumber.js' import { BIG_ZERO, OSQUEETH_DECIMALS } from '@constants/index' import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom } from '../contracts/atoms' @@ -13,6 +13,7 @@ import { Price, Token } from '@uniswap/sdk-core' import { useHandleTransaction } from '../wallet/hooks' import { squeethPriceeAtom, wethPriceAtom } from '../squeethPool/atoms' import ethers from 'ethers' +import { useGetSellQuote } from '../squeethPool/hooks' // Close position with flashloan export const useClosePosition = () => { @@ -86,22 +87,7 @@ export const useOpenPosition = () => { // Closest 60 tick width above or below current tick (60 is minimum tick width for 30bps pool) - // Closest valid lower tick - const lowerTickBelow = lowerTickInput - (lowerTickInput % 60) - const lowerTickAbove = lowerTickInput + (lowerTickInput % 60) - const lowerTick = - Math.abs(lowerTickAbove - lowerTickInput) < Math.abs(lowerTickBelow - lowerTickInput) - ? lowerTickAbove - : lowerTickBelow - - // TODO: ensure we're not hitting a bound for a tick - // Closest valid upper tick - const upperTickBelow = upperTickInput - (upperTickInput % 60) - const upperTickAbove = upperTickInput + (upperTickInput % 60) - const upperTick = - Math.abs(upperTickAbove - upperTickInput) < Math.abs(upperTickBelow - upperTickInput) - ? upperTickAbove - : upperTickBelow + const [lowerTick, upperTick] = validTicks(lowerTickInput, upperTickInput) const params = { recipient: address, @@ -179,3 +165,133 @@ export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: num } return tickToPrice(baseToken, quoteToken, tick) } + +export function validTicks(lowerTickInput: number, upperTickInput: number) { + // Closest valid lower tick + const lowerTickBelow = lowerTickInput - (lowerTickInput % 60) + const lowerTickAbove = lowerTickInput + (lowerTickInput % 60) + const lowerTick = + Math.abs(lowerTickAbove - lowerTickInput) < Math.abs(lowerTickBelow - lowerTickInput) + ? lowerTickAbove + : lowerTickBelow + + // TODO: ensure we're not hitting a bound for a tick + // Closest valid upper tick + const upperTickBelow = upperTickInput - (upperTickInput % 60) + const upperTickAbove = upperTickInput + (upperTickInput % 60) + const upperTick = + Math.abs(upperTickAbove - upperTickInput) < Math.abs(upperTickBelow - upperTickInput) + ? upperTickAbove + : upperTickBelow + return [lowerTick, upperTick] +} + +// Rebalance via general swap +export const useRebalanceGeneralSwap = () => { + const address = useAtomValue(addressAtom) + const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) + const { controllerHelper, weth, oSqueeth, squeethPool } = useAtomValue(addressesAtom) + const controllerContract = useAtomValue(controllerContractAtom) + const handleTransaction = useHandleTransaction() + const ethPrice = useAtomValue(wethPriceAtom) + const positionManager = useAtomValue(nftManagerContractAtom) + const isWethToken0 = useAtomValue(isWethToken0Atom) + const getSellQuote = useGetSellQuote() + const rebalanceGeneralSwap = useAppCallback( + async (vaultId: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { + if (!controllerContract || !controllerHelperContract || !address || !positionManager) return + const one = new BigNumber(10).pow(18) + const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId + const positionBefore = await positionManager.methods.positions(uniTokenId) + const vaultBefore = await controllerContract?.methods.vaults(vaultId) + const scaledEthPrice = ethPrice.div(10000) + const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one) + const collateralToFlashloan = debtInEth.mul(3).div(2).add(0.01) + const tokenIndex = await positionManager.methods.totalSupply() + const tokenId = await positionManager.methods.tokenByIndex(tokenIndex.sub(1)) + const amount0Min = new BigNumber(0) + const amount1Min = new BigNumber(0) + const safetyWPowerPerp = ethers.utils.parseUnits('0.01') + + const [lowerTick, upperTick] = validTicks(lowerTickInput, upperTickInput) + + // Get current LPpositions + const [amount0, amount1] = await positionManager.methods.decreaseLiquidity({ + tokenId: tokenId, + liquidity: positionBefore.liquidity, + amount0Min: 0, + amount1Min: 0, + deadline: Math.floor(Date.now() / 1000 + 1800), + }) + const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 + const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 + + // Estimate proceeds from liquidating squeeth in LP + const ethAmountOutFromSwap = getSellQuote(wPowerPerpAmountInLPBefore) + + // Estimate of new LP with 0.01 weth safety margin + const safetyEth = ethers.utils.parseUnits('0.01') + const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap).sub(safetyEth) + + const abiCoder = new ethers.utils.AbiCoder() + const rebalanceLpInVaultParams = [ + { + // Liquidate LP + rebalanceLpInVaultType: new BigNumber(1), // DecreaseLpLiquidity: + // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min] + data: abiCoder.encode( + ['uint256', 'uint256', 'uint256', 'uint128', 'uint128'], + [ + tokenId, + positionBefore.liquidity, + new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toString(), + new BigNumber(0).toString(), + new BigNumber(0).toString(), + ], + ), + }, + { + // Sell all oSQTH for ETH + rebalanceLpInVaultType: new BigNumber(5), // GeneralSwap: + // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice] + data: abiCoder.encode( + ['address', 'address', 'uint256', 'uint256', 'uint24'], + [oSqueeth, weth, wPowerPerpAmountInLPBefore.sub(safetyWPowerPerp), new BigNumber(0).toString(), 3000], + ), + }, + { + // Mint new LP + rebalanceLpInVaultType: new BigNumber(4).toString(), // MintNewLP + // lpWPowerPerpPool: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ] + data: abiCoder.encode( + ['address', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'], + [ + controllerHelper, + squeethPool, + vaultId, + new BigNumber(0).toString(), + new BigNumber(0).toString(), + wethAmountToLP, + amount0Min, + amount1Min, + lowerTick, + upperTick, + ], + ), + }, + ] + + await controllerContract.methods.updateOperator(vaultId, controllerHelper) + return handleTransaction( + await controllerHelperContract.methods + .rebalanceLpInVault(vaultId, collateralToFlashloan, rebalanceLpInVaultParams) + .send({ + from: address, + }), + onTxConfirmed, + ) + }, + [], + ) + return rebalanceGeneralSwap +} From 0542b4a1ce0106939678088d768c378d1cf89364 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 15 Jun 2022 19:08:42 -0700 Subject: [PATCH 06/82] rebalance via vault --- packages/frontend/src/state/lp/hooks.ts | 116 ++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 22a4daeeb..88223105c 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -186,6 +186,122 @@ export function validTicks(lowerTickInput: number, upperTickInput: number) { return [lowerTick, upperTick] } +// Rebalance via vault +export const useRebalanceVault = () => { + const address = useAtomValue(addressAtom) + const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) + const { controllerHelper, weth, oSqueeth, squeethPool } = useAtomValue(addressesAtom) + const controllerContract = useAtomValue(controllerContractAtom) + const handleTransaction = useHandleTransaction() + const ethPrice = useAtomValue(wethPriceAtom) + const positionManager = useAtomValue(nftManagerContractAtom) + const isWethToken0 = useAtomValue(isWethToken0Atom) + const getSellQuote = useGetSellQuote() + const rebalanceVault = useAppCallback( + async (vaultId: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { + if (!controllerContract || !controllerHelperContract || !address || !positionManager) return + const one = new BigNumber(10).pow(18) + const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId + const positionBefore = await positionManager.methods.positions(uniTokenId) + const vaultBefore = await controllerContract?.methods.vaults(vaultId) + const scaledEthPrice = ethPrice.div(10000) + const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one) + const collateralToFlashloan = debtInEth.mul(3).div(2).add(0.01) + const tokenIndex = await positionManager.methods.totalSupply() + const tokenId = await positionManager.methods.tokenByIndex(tokenIndex.sub(1)) + const amount0Min = new BigNumber(0) + const amount1Min = new BigNumber(0) + const safetyWPowerPerp = ethers.utils.parseUnits('0.01') + + const [lowerTick, upperTick] = validTicks(lowerTickInput, upperTickInput) + + // Get current LPpositions + const [amount0, amount1] = await positionManager.methods.decreaseLiquidity({ + tokenId: tokenId, + liquidity: positionBefore.liquidity, + amount0Min: 0, + amount1Min: 0, + deadline: Math.floor(Date.now() / 1000 + 1800), + }) + const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 + const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 + + // Estimate proceeds from liquidating squeeth in LP + const ethAmountOutFromSwap = getSellQuote(wPowerPerpAmountInLPBefore) + + // Estimate of new LP with 0.01 weth safety margin + const safetyEth = ethers.utils.parseUnits('0.01') + const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap).sub(safetyEth) + + const abiCoder = new ethers.utils.AbiCoder() + const rebalanceLpInVaultParams = [ + { + // Liquidate LP + rebalanceLpInVaultType: new BigNumber(1), // DecreaseLpLiquidity: + // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min] + data: abiCoder.encode( + ['uint256', 'uint256', 'uint256', 'uint128', 'uint128'], + [ + tokenId, + positionBefore.liquidity, + new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toString(), + new BigNumber(0).toString(), + new BigNumber(0).toString(), + ], + ), + }, + { + // Deposit into vault and mint + rebalanceLpInVaultType: new BigNumber(2).toString(), // DepositIntoVault + // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit] + data: abiCoder.encode(['uint256', 'uint256'], [wPowerPerpAmountInLPBefore, wethAmountInLPBefore]), + }, + { + // Withdraw from vault + rebalanceLpInVaultType: new BigNumber(3), // WithdrawFromVault + // withdrawFromVault: [wPowerPerpToBurn, collateralToWithdraw, burnExactRemoved ] + data: abiCoder.encode( + ['uint256', 'uint256', 'bool'], + [wPowerPerpAmountInLPBefore, wethAmountInLPBefore, false], + ), + }, + { + // Mint new LP + rebalanceLpInVaultType: new BigNumber(4).toString(), // MintNewLP + // lpWPowerPerpPool: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ] + data: abiCoder.encode( + ['address', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'], + [ + controllerHelper, + squeethPool, + vaultId, + new BigNumber(0).toString(), + new BigNumber(0).toString(), + wethAmountToLP, + amount0Min, + amount1Min, + lowerTick, + upperTick, + ], + ), + }, + ] + + await controllerContract.methods.updateOperator(vaultId, controllerHelper) + return handleTransaction( + await controllerHelperContract.methods + .rebalanceLpInVault(vaultId, collateralToFlashloan, rebalanceLpInVaultParams) + .send({ + from: address, + }), + onTxConfirmed, + ) + }, + [], + ) + return rebalanceVault +} + // Rebalance via general swap export const useRebalanceGeneralSwap = () => { const address = useAtomValue(addressAtom) From 75cadc73654be9420b503830b78eea92a42eeb23 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 15 Jun 2022 19:34:50 -0700 Subject: [PATCH 07/82] flashloanWMintDeposit open position --- packages/frontend/src/state/lp/hooks.ts | 69 ++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 88223105c..f43fd34e4 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -15,6 +15,9 @@ import { squeethPriceeAtom, wethPriceAtom } from '../squeethPool/atoms' import ethers from 'ethers' import { useGetSellQuote } from '../squeethPool/hooks' +// CONSTANTS +const one = new BigNumber(10).pow(18) + // Close position with flashloan export const useClosePosition = () => { const address = useAtomValue(addressAtom) @@ -117,6 +120,71 @@ export const useOpenPosition = () => { return openPosition } +// Opening a mint and LP position and depositing +export const useOpenPositionDeposit = () => { + const { squeethPool } = useAtomValue(addressesAtom) + const normalizationFactor = useAtomValue(normFactorAtom) + const address = useAtomValue(addressAtom) + const contract = useAtomValue(controllerHelperHelperContractAtom) + const handleTransaction = useHandleTransaction() + const normFactor = useAtomValue(normFactorAtom) + const ethPrice = useAtomValue(wethPriceAtom) + const squeethPrice = useAtomValue(squeethPriceeAtom) + const openPositionDeposit = useAppCallback( + async ( + ethAmount: BigNumber, + squeethToMint: BigNumber, + lowerTickInput: number, + upperTickInput: number, + onTxConfirmed?: () => void, + ) => { + const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS).multipliedBy(normalizationFactor) + const mintRSqueethAmount = mintWSqueethAmount.multipliedBy(normFactor).div(one) + const scaledEthPrice = ethPrice.div(10000) + const debtInEth = mintRSqueethAmount.multipliedBy(scaledEthPrice).div(one) + + // Do we want to hardcode a 150% collateralization ratio? + const collateralToMint = debtInEth.multipliedBy(3).div(2).plus(0.01) + const collateralToLp = mintWSqueethAmount.multipliedBy(squeethPrice).div(one) + const flashloanFee = collateralToMint.multipliedBy(9).div(1000) + + // Closest 60 tick width above or below current tick (60 is minimum tick width for 30bps pool) + + const [lowerTick, upperTick] = validTicks(lowerTickInput, upperTickInput) + + const flashloanWMintDepositNftParams = { + wPowerPerpPool: squeethPool, + vaultId: 0, + wPowerPerpAmount: mintWSqueethAmount.toString(), + collateralToDeposit: collateralToMint.toString(), + collateralToFlashloan: collateralToMint.toString(), + collateralToLp: collateralToLp.toString(), + collateralToWithdraw: 0, + amount0Min: 0, + amount1Min: 0, + lowerTick: lowerTick, + upperTick: upperTick, + } + + if (!contract || !address) return null + + return handleTransaction( + contract.methods + .flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, { + value: collateralToLp.plus(flashloanFee).plus(0.01).toString(), + }) + .send({ + from: address, + value: fromTokenAmount(ethAmount, 18), + }), + onTxConfirmed, + ) + }, + [], + ) + return openPositionDeposit +} + // Collect fees export const useCollectFees = () => { const address = useAtomValue(addressAtom) @@ -128,7 +196,6 @@ export const useCollectFees = () => { const positionManager = useAtomValue(nftManagerContractAtom) const collectFees = useAppCallback(async (vaultId: BigNumber, onTxConfirmed?: () => void) => { if (!controllerContract || !controllerHelperContract || !address || !positionManager) return - const one = new BigNumber(10).pow(18) const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId const vaultBefore = await controllerContract?.methods.vaults(vaultId) const scaledEthPrice = ethPrice.div(10000) From 36c671c3398b60efcff4964c7799149dbd564b9d Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 16 Jun 2022 16:51:49 -0700 Subject: [PATCH 08/82] next tick price getter func --- packages/frontend/src/state/lp/atoms.ts | 16 +---- packages/frontend/src/state/lp/hooks.ts | 77 ++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/packages/frontend/src/state/lp/atoms.ts b/packages/frontend/src/state/lp/atoms.ts index 2b94ac0fe..5bd82a0d9 100644 --- a/packages/frontend/src/state/lp/atoms.ts +++ b/packages/frontend/src/state/lp/atoms.ts @@ -1,17 +1,5 @@ import { atom } from 'jotai' import { BIG_ZERO } from '@constants/index' -export const ethCollateralPnlAtom = atom(BIG_ZERO) -export const shortUnrealizedPNLAtom = atom({ usd: BIG_ZERO, eth: BIG_ZERO, loading: true }) -export const longUnrealizedPNLAtom = atom({ usd: BIG_ZERO, eth: BIG_ZERO, loading: true }) -export const buyQuoteAtom = atom(BIG_ZERO) -export const sellQuoteAtom = atom({ - amountOut: BIG_ZERO, - minimumAmountOut: BIG_ZERO, - priceImpact: '0', - pools: Array>(), -}) - -export const longGainAtom = atom(BIG_ZERO) -export const shortGainAtom = atom(BIG_ZERO) -export const loadingAtom = atom(true) +export const lowerTickAtom = atom(BIG_ZERO) +export const upperTickAtom = atom(BIG_ZERO) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index f43fd34e4..e49586f8a 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -1,4 +1,4 @@ -import { tickToPrice } from '@uniswap/v3-sdk' +import { FeeAmount, nearestUsableTick, TickMath, tickToPrice, TICK_SPACINGS } from '@uniswap/v3-sdk' import { fromTokenAmount } from '@utils/calculations' import { useAtom, useAtomValue } from 'jotai' @@ -11,12 +11,21 @@ import { addressAtom } from '../wallet/atoms' import { normFactorAtom } from '../controller/atoms' import { Price, Token } from '@uniswap/sdk-core' import { useHandleTransaction } from '../wallet/hooks' -import { squeethPriceeAtom, wethPriceAtom } from '../squeethPool/atoms' +import { squeethPriceeAtom, squeethTokenAtom, wethPriceAtom, wethTokenAtom } from '../squeethPool/atoms' import ethers from 'ethers' import { useGetSellQuote } from '../squeethPool/hooks' +import { useUpdateAtom } from 'jotai/utils' +import { lowerTickAtom, upperTickAtom } from './atoms' +import { useMemo } from 'react' -// CONSTANTS +/*** CONSTANTS ***/ const one = new BigNumber(10).pow(18) +export enum Bound { + LOWER = 'LOWER', + UPPER = 'UPPER', +} + +/*** ACTIONS ***/ // Close position with flashloan export const useClosePosition = () => { @@ -478,3 +487,65 @@ export const useRebalanceGeneralSwap = () => { ) return rebalanceGeneralSwap } + +/*** GETTERS ***/ +// Get next tick price +export const useGetNextTickPrice = () => { + const setLowerTick = useUpdateAtom(lowerTickAtom) + const setUpperTick = useUpdateAtom(upperTickAtom) + const lowerTick = useAtomValue(lowerTickAtom) + const upperTick = useAtomValue(upperTickAtom) + const isWethToken0 = useAtomValue(isWethToken0Atom) + const squeethToken = useAtomValue(squeethTokenAtom) + const wethToken = useAtomValue(wethTokenAtom) + const getNextTickPrice = useAppCallback(async (getHigherTick: boolean, isUpperTick: boolean) => { + const atLimit = useIsTickAtLimit(3000, lowerTick.toNumber(), upperTick.toNumber()) + + if (isUpperTick) { + const newUpperTick = !getHigherTick + ? upperTick.minus(TICK_SPACINGS[3000]) + : !atLimit + ? upperTick.plus(TICK_SPACINGS[3000]) + : null + if (newUpperTick) { + setUpperTick(newUpperTick) + return isWethToken0 + ? tickToPrice(wethToken!, squeethToken!, newUpperTick.toNumber()) + : tickToPrice(squeethToken!, wethToken!, newUpperTick.toNumber()) + } + } else { + const newLowerTick = getHigherTick + ? lowerTick.plus(TICK_SPACINGS[3000]) + : !atLimit + ? lowerTick.minus(TICK_SPACINGS[3000]) + : null + if (newLowerTick) { + setLowerTick(newLowerTick) + return isWethToken0 + ? tickToPrice(wethToken!, squeethToken!, newLowerTick.toNumber()) + : tickToPrice(squeethToken!, wethToken!, newLowerTick.toNumber()) + } + } + }, []) + return getNextTickPrice +} + +export default function useIsTickAtLimit( + feeAmount: FeeAmount | undefined, + tickLower: number | undefined, + tickUpper: number | undefined, +) { + return useMemo( + () => ({ + [Bound.LOWER]: + feeAmount && tickLower + ? tickLower === nearestUsableTick(TickMath.MIN_TICK, TICK_SPACINGS[feeAmount as FeeAmount]) + : undefined, + [Bound.UPPER]: + feeAmount && tickUpper + ? tickUpper === nearestUsableTick(TickMath.MAX_TICK, TICK_SPACINGS[feeAmount as FeeAmount]) + : undefined, + }), + [feeAmount, tickLower, tickUpper], + ) +} From 7c0920bf248c1c0f5dd0cacdc361f0d75c5f575d Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 16 Jun 2022 17:14:32 -0700 Subject: [PATCH 09/82] using nearestUsableTick --- packages/frontend/src/state/lp/hooks.ts | 32 +++++++------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index e49586f8a..17c28a202 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -99,7 +99,8 @@ export const useOpenPosition = () => { // Closest 60 tick width above or below current tick (60 is minimum tick width for 30bps pool) - const [lowerTick, upperTick] = validTicks(lowerTickInput, upperTickInput) + const lowerTick = nearestUsableTick(lowerTickInput, 3000) + const upperTick = nearestUsableTick(upperTickInput, 3000) const params = { recipient: address, @@ -159,7 +160,8 @@ export const useOpenPositionDeposit = () => { // Closest 60 tick width above or below current tick (60 is minimum tick width for 30bps pool) - const [lowerTick, upperTick] = validTicks(lowerTickInput, upperTickInput) + const lowerTick = nearestUsableTick(lowerTickInput, 3000) + const upperTick = nearestUsableTick(upperTickInput, 3000) const flashloanWMintDepositNftParams = { wPowerPerpPool: squeethPool, @@ -242,26 +244,6 @@ export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: num return tickToPrice(baseToken, quoteToken, tick) } -export function validTicks(lowerTickInput: number, upperTickInput: number) { - // Closest valid lower tick - const lowerTickBelow = lowerTickInput - (lowerTickInput % 60) - const lowerTickAbove = lowerTickInput + (lowerTickInput % 60) - const lowerTick = - Math.abs(lowerTickAbove - lowerTickInput) < Math.abs(lowerTickBelow - lowerTickInput) - ? lowerTickAbove - : lowerTickBelow - - // TODO: ensure we're not hitting a bound for a tick - // Closest valid upper tick - const upperTickBelow = upperTickInput - (upperTickInput % 60) - const upperTickAbove = upperTickInput + (upperTickInput % 60) - const upperTick = - Math.abs(upperTickAbove - upperTickInput) < Math.abs(upperTickBelow - upperTickInput) - ? upperTickAbove - : upperTickBelow - return [lowerTick, upperTick] -} - // Rebalance via vault export const useRebalanceVault = () => { const address = useAtomValue(addressAtom) @@ -289,7 +271,8 @@ export const useRebalanceVault = () => { const amount1Min = new BigNumber(0) const safetyWPowerPerp = ethers.utils.parseUnits('0.01') - const [lowerTick, upperTick] = validTicks(lowerTickInput, upperTickInput) + const lowerTick = nearestUsableTick(lowerTickInput, 3000) + const upperTick = nearestUsableTick(upperTickInput, 3000) // Get current LPpositions const [amount0, amount1] = await positionManager.methods.decreaseLiquidity({ @@ -405,7 +388,8 @@ export const useRebalanceGeneralSwap = () => { const amount1Min = new BigNumber(0) const safetyWPowerPerp = ethers.utils.parseUnits('0.01') - const [lowerTick, upperTick] = validTicks(lowerTickInput, upperTickInput) + const lowerTick = nearestUsableTick(lowerTickInput, 3000) + const upperTick = nearestUsableTick(upperTickInput, 3000) // Get current LPpositions const [amount0, amount1] = await positionManager.methods.decreaseLiquidity({ From db6d0f4814640b984138b63796529810e31d5f95 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 16 Jun 2022 18:09:15 -0700 Subject: [PATCH 10/82] fixing abi --- .../frontend/src/abis/controllerHelper.json | 1559 ++++++++--------- 1 file changed, 690 insertions(+), 869 deletions(-) diff --git a/packages/frontend/src/abis/controllerHelper.json b/packages/frontend/src/abis/controllerHelper.json index a007d7943..af7d38d9d 100644 --- a/packages/frontend/src/abis/controllerHelper.json +++ b/packages/frontend/src/abis/controllerHelper.json @@ -1,891 +1,712 @@ -{ - "address": "0xfa86d43b41Fa7a759c606130cc81970A955ff816", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_controller", - "type": "address" - }, - { - "internalType": "address", - "name": "_nonfungiblePositionManager", - "type": "address" - }, - { - "internalType": "address", - "name": "_uniswapFactory", - "type": "address" - }, - { - "internalType": "address", - "name": "_exec", - "type": "address" - }, - { - "internalType": "address", - "name": "_euler", - "type": "address" - }, - { - "internalType": "address", - "name": "_dToken", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "vaultId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidityPercentage", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmountToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToWithdraw", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limitPriceEthPerPowerPerp", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "amount0Min", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "amount1Min", - "type": "uint128" - }, - { - "internalType": "uint24", - "name": "poolFee", - "type": "uint24" - }, - { - "internalType": "bool", - "name": "burnExactRemoved", - "type": "bool" - } - ], - "internalType": "struct ControllerHelperDataType.CloseShortWithUserNftParams", - "name": "_params", - "type": "tuple" - } - ], - "name": "closeShortWithUserNft", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "dToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "euler", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "exec", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "vaultId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidityPercentage", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmountToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToFlashloan", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToWithdraw", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limitPriceEthPerPowerPerp", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "amount0Min", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "amount1Min", - "type": "uint128" - }, - { - "internalType": "uint24", - "name": "poolFee", - "type": "uint24" - }, - { - "internalType": "bool", - "name": "burnExactRemoved", - "type": "bool" - } - ], - "internalType": "struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam", - "name": "_params", - "type": "tuple" - } - ], - "name": "flashloanCloseVaultLpNft", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "wPowerPerpPool", - "type": "address" - }, - { - "internalType": "uint256", - "name": "vaultId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToFlashloan", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToLp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToWithdraw", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount0Min", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount1Min", - "type": "uint256" - }, - { - "internalType": "int24", - "name": "lowerTick", - "type": "int24" - }, - { - "internalType": "int24", - "name": "upperTick", - "type": "int24" - } - ], - "internalType": "struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams", - "name": "_params", - "type": "tuple" - } - ], - "name": "flashloanWMintLpDepositNft", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "vaultId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmountToMint", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmountToSell", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minToReceive", - "type": "uint256" - }, - { - "internalType": "uint24", - "name": "poolFee", - "type": "uint24" - } - ], - "internalType": "struct ControllerHelperDataType.FlashSellLongWMintParams", - "name": "_params", - "type": "tuple" - } - ], - "name": "flashswapSellLongWMint", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "vaultId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmountToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmountToBuy", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToWithdraw", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxToPay", - "type": "uint256" - }, - { - "internalType": "uint24", - "name": "poolFee", - "type": "uint24" - } - ], - "internalType": "struct ControllerHelperDataType.FlashswapWBurnBuyLongParams", - "name": "_params", - "type": "tuple" - } - ], - "name": "flashswapWBurnBuyLong", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedData", - "type": "bytes" - } - ], - "name": "onDeferredLiquidityCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_vaultId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_collateralToFlashloan", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "enum ControllerHelperDataType.RebalanceVaultNftType", - "name": "rebalanceLpInVaultType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct ControllerHelperDataType.RebalanceLpInVaultParams[]", - "name": "_params", - "type": "tuple[]" - } - ], - "name": "rebalanceLpInVault", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "wPowerPerpPool", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmountDesired", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wethAmountDesired", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount0DesiredMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount1DesiredMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limitPriceEthPerPowerPerp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount0Min", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount1Min", - "type": "uint256" - }, - { - "internalType": "int24", - "name": "lowerTick", - "type": "int24" - }, - { - "internalType": "int24", - "name": "upperTick", - "type": "int24" - }, - { - "internalType": "uint24", - "name": "poolFee", - "type": "uint24" - } - ], - "internalType": "struct ControllerHelperDataType.RebalanceLpWithoutVaultParams", - "name": "_params", - "type": "tuple" - } - ], - "name": "rebalanceLpWithoutVault", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidityPercentage", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "amount0Min", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "amount1Min", - "type": "uint128" - }, - { - "internalType": "uint256", - "name": "limitPriceEthPerPowerPerp", - "type": "uint256" - }, - { - "internalType": "uint24", - "name": "poolFee", - "type": "uint24" - } - ], - "internalType": "struct ControllerHelperDataType.ReduceLiquidityAndSellParams", - "name": "_params", - "type": "tuple" - } - ], - "name": "reduceLiquidityAndSell", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "token", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "amount0Delta", - "type": "int256" - }, - { - "internalType": "int256", - "name": "amount1Delta", - "type": "int256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "uniswapV3SwapCallback", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "wPowerPerpPool", - "type": "address" - }, - { - "internalType": "uint256", - "name": "vaultId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "wPowerPerpAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "collateralToLp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount0Min", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount1Min", - "type": "uint256" - }, - { - "internalType": "int24", - "name": "lowerTick", - "type": "int24" - }, - { - "internalType": "int24", - "name": "upperTick", - "type": "int24" - } - ], - "internalType": "struct ControllerHelperDataType.MintAndLpParams", - "name": "_params", - "type": "tuple" - } - ], - "name": "wMintLp", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", - "receipt": { - "to": null, - "from": "0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA", - "contractAddress": "0xfa86d43b41Fa7a759c606130cc81970A955ff816", - "transactionIndex": 166, - "gasUsed": "5438748", - "logsBloom": "0x00800000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000002010000080000000000000000200000000000000000800000000000400000000000000000000000000008000000000002000000000004100001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000200000000000000000000040002000000000020000000000000000000000000000000000000000020000000010200800000000000000000000000800000000000000000000000000000000", - "blockHash": "0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6", - "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", - "logs": [ +[ + { + "inputs": [ { - "transactionIndex": 166, - "blockNumber": 14925294, - "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", - "address": "0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B", - "topics": [ - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816", - "0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88" - ], - "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 237, - "blockHash": "0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6" + "internalType": "address", + "name": "_controller", + "type": "address" }, { - "transactionIndex": 166, - "blockNumber": 14925294, - "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", - "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "topics": [ - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816", - "0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88" - ], - "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "logIndex": 238, - "blockHash": "0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6" + "internalType": "address", + "name": "_nonfungiblePositionManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_uniswapFactory", + "type": "address" }, { - "transactionIndex": 166, - "blockNumber": 14925294, - "transactionHash": "0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4", - "address": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88", - "topics": [ - "0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31", - "0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816", - "0x00000000000000000000000064187ae08781b09368e6253f9e94951243a493d5" + "internalType": "address", + "name": "_exec", + "type": "address" + }, + { + "internalType": "address", + "name": "_euler", + "type": "address" + }, + { + "internalType": "address", + "name": "_dToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidityPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToWithdraw", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limitPriceEthPerPowerPerp", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0Min", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Min", + "type": "uint128" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + }, + { + "internalType": "bool", + "name": "burnExactRemoved", + "type": "bool" + } ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 239, - "blockHash": "0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6" + "internalType": "struct ControllerHelperDataType.CloseShortWithUserNftParams", + "name": "_params", + "type": "tuple" } ], - "blockNumber": 14925294, - "cumulativeGasUsed": "17334095", - "status": 1, - "byzantium": true + "name": "closeShortWithUserNft", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, - "args": [ - "0x64187ae08781B09368e6253F9E94951243A493D5", - "0xC36442b4a4522E871399CD717aBDD847Ab11FE88", - "0x1F98431c8aD98523631AE4a59f267346ea31F984", - "0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80", - "0x27182842E098f60e3D576794A5bFFb0777E025d3", - "0x62e28f054efc24b26A794F5C1249B6349454352C" - ], - "solcInputHash": "fc32ed9e00a9017e491333926bef5473", - "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_controller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_nonfungiblePositionManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_uniswapFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_exec\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_euler\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityPercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToBurn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToWithdraw\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limitPriceEthPerPowerPerp\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"amount0Min\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Min\",\"type\":\"uint128\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"},{\"internalType\":\"bool\",\"name\":\"burnExactRemoved\",\"type\":\"bool\"}],\"internalType\":\"struct ControllerHelperDataType.CloseShortWithUserNftParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"closeShortWithUserNft\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"euler\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exec\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityPercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToBurn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToFlashloan\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToWithdraw\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limitPriceEthPerPowerPerp\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"amount0Min\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Min\",\"type\":\"uint128\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"},{\"internalType\":\"bool\",\"name\":\"burnExactRemoved\",\"type\":\"bool\"}],\"internalType\":\"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"flashloanCloseVaultLpNft\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"wPowerPerpPool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToDeposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToFlashloan\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToLp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToWithdraw\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0Min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Min\",\"type\":\"uint256\"},{\"internalType\":\"int24\",\"name\":\"lowerTick\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"upperTick\",\"type\":\"int24\"}],\"internalType\":\"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"flashloanWMintLpDepositNft\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToMint\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToDeposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToSell\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToReceive\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"}],\"internalType\":\"struct ControllerHelperDataType.FlashSellLongWMintParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"flashswapSellLongWMint\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToBurn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountToBuy\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToWithdraw\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxToPay\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"}],\"internalType\":\"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"flashswapWBurnBuyLong\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedData\",\"type\":\"bytes\"}],\"name\":\"onDeferredLiquidityCheck\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_collateralToFlashloan\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"enum ControllerHelperDataType.RebalanceVaultNftType\",\"name\":\"rebalanceLpInVaultType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\",\"name\":\"_params\",\"type\":\"tuple[]\"}],\"name\":\"rebalanceLpInVault\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"wPowerPerpPool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmountDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wethAmountDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0DesiredMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1DesiredMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limitPriceEthPerPowerPerp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0Min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Min\",\"type\":\"uint256\"},{\"internalType\":\"int24\",\"name\":\"lowerTick\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"upperTick\",\"type\":\"int24\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"}],\"internalType\":\"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"rebalanceLpWithoutVault\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidityPercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"amount0Min\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Min\",\"type\":\"uint128\"},{\"internalType\":\"uint256\",\"name\":\"limitPriceEthPerPowerPerp\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"poolFee\",\"type\":\"uint24\"}],\"internalType\":\"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"reduceLiquidityAndSell\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"wPowerPerpPool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"wPowerPerpAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToDeposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateralToLp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0Min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Min\",\"type\":\"uint256\"},{\"internalType\":\"int24\",\"name\":\"lowerTick\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"upperTick\",\"type\":\"int24\"}],\"internalType\":\"struct ControllerHelperDataType.MintAndLpParams\",\"name\":\"_params\",\"type\":\"tuple\"}],\"name\":\"wMintLp\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\":{\"details\":\"user should approve this contract for Uni NFT transfer\",\"params\":{\"_params\":\"ControllerHelperDataType.CloseShortWithUserNftParams struct\"}},\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\":{\"details\":\"sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\",\"params\":{\"_params\":\"ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\"}},\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\":{\"details\":\"flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\",\"params\":{\"_params\":\"ControllerHelperDataType.FlashSellLongWMintParams struct\"}},\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\":{\"details\":\"this function\",\"params\":{\"_params\":\"ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\"}},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"accept erc721 from safeTransferFrom and safeMint after callback\",\"returns\":{\"_0\":\"returns received selector\"}},\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\":{\"params\":{\"_collateralToFlashloan\":\"collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\",\"_params\":\"array of ControllerHelperDataType.RebalanceLpInVaultParams structs\",\"_vaultId\":\"vault ID\"}},\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\":{\"params\":{\"_params\":\"ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\"}},\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\":{\"params\":{\"_params\":\"ControllerHelperDataType.ReduceLiquidityAndSellParams struct\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"params\":{\"_data\":\"callback data encoded as SwapCallbackData struct\",\"amount0Delta\":\"amount of token0\",\"amount1Delta\":\"amount of token1\"}},\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\":{\"params\":{\"_params\":\"ControllerHelperDataType.MintAndLpParams struct\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\":{\"notice\":\"close short position with user Uniswap v3 LP NFT\"},\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\":{\"notice\":\"FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\"},\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\":{\"notice\":\"sell long wPowerPerp and flashswap mint short position\"},\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\":{\"notice\":\"flash close position and buy long squeeth\"},\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\":{\"notice\":\"Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\"},\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\":{\"notice\":\"Rebalance LP nft through trading\"},\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\":{\"notice\":\"sell all LP wPowerPerp amounts to WETH and send back to user\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"uniswap swap callback function for flashswap\"},\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\":{\"notice\":\"mint WPowerPerp and LP into Uniswap v3 pool\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/periphery/ControllerHelper.sol\":\"ControllerHelper\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\":\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, 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 `sender` to `recipient` 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(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n */\\n function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\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 function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 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 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\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(address target, bytes memory data, string memory errorMessage) 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(address target, bytes memory data, uint256 value) 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(address target, bytes memory data, uint256 value, string memory errorMessage) 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 // solhint-disable-next-line avoid-low-level-calls\\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(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\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(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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\\n // solhint-disable-next-line no-inline-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\":\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\",\"license\":\"MIT\"},\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n IUniswapV3PoolImmutables,\\n IUniswapV3PoolState,\\n IUniswapV3PoolDerivedState,\\n IUniswapV3PoolActions,\\n IUniswapV3PoolOwnerActions,\\n IUniswapV3PoolEvents\\n{\\n\\n}\\n\",\"keccak256\":\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n function uniswapV3FlashCallback(\\n uint256 fee0,\\n uint256 fee1,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x151ba1777392771025f0fca946c95fbc16ec4b5eff05e1f236115b99bd574de2\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#swap\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\ninterface IUniswapV3SwapCallback {\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissionless pool actions\\n/// @notice Contains pool methods that can be called by anyone\\ninterface IUniswapV3PoolActions {\\n /// @notice Sets the initial price for the pool\\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\n function initialize(uint160 sqrtPriceX96) external;\\n\\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\n /// @param recipient The address for which the liquidity will be created\\n /// @param tickLower The lower tick of the position in which to add liquidity\\n /// @param tickUpper The upper tick of the position in which to add liquidity\\n /// @param amount The amount of liquidity to mint\\n /// @param data Any data that should be passed through to the callback\\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n function mint(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount,\\n bytes calldata data\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Collects tokens owed to a position\\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\n /// @param recipient The address which should receive the fees collected\\n /// @param tickLower The lower tick of the position for which to collect fees\\n /// @param tickUpper The upper tick of the position for which to collect fees\\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\n /// @return amount0 The amount of fees collected in token0\\n /// @return amount1 The amount of fees collected in token1\\n function collect(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n\\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\n /// @dev Fees must be collected separately via a call to #collect\\n /// @param tickLower The lower tick of the position for which to burn liquidity\\n /// @param tickUpper The upper tick of the position for which to burn liquidity\\n /// @param amount How much liquidity to burn\\n /// @return amount0 The amount of token0 sent to the recipient\\n /// @return amount1 The amount of token1 sent to the recipient\\n function burn(\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Swap token0 for token1, or token1 for token0\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\n /// @param recipient The address to receive the output of the swap\\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\n /// @param data Any data to be passed through to the callback\\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n\\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\n /// @param recipient The address which will receive the token0 and token1 amounts\\n /// @param amount0 The amount of token0 to send\\n /// @param amount1 The amount of token1 to send\\n /// @param data Any data to be passed through to the callback\\n function flash(\\n address recipient,\\n uint256 amount0,\\n uint256 amount1,\\n bytes calldata data\\n ) external;\\n\\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\n /// the input observationCardinalityNext.\\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\n function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\n}\\n\",\"keccak256\":\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that is not stored\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\n/// blockchain. The functions here may have variable gas costs.\\ninterface IUniswapV3PoolDerivedState {\\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\n /// you must call it with secondsAgos = [3600, 0].\\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\n /// timestamp\\n function observe(uint32[] calldata secondsAgos)\\n external\\n view\\n returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\n\\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\n /// snapshot is taken and the second snapshot is taken.\\n /// @param tickLower The lower tick of the range\\n /// @param tickUpper The upper tick of the range\\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\n /// @return secondsInside The snapshot of seconds per liquidity for the range\\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (\\n int56 tickCumulativeInside,\\n uint160 secondsPerLiquidityInsideX128,\\n uint32 secondsInside\\n );\\n}\\n\",\"keccak256\":\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Events emitted by a pool\\n/// @notice Contains all events emitted by the pool\\ninterface IUniswapV3PoolEvents {\\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\n event Initialize(uint160 sqrtPriceX96, int24 tick);\\n\\n /// @notice Emitted when liquidity is minted for a given position\\n /// @param sender The address that minted the liquidity\\n /// @param owner The owner of the position and recipient of any minted liquidity\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity minted to the position range\\n /// @param amount0 How much token0 was required for the minted liquidity\\n /// @param amount1 How much token1 was required for the minted liquidity\\n event Mint(\\n address sender,\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted when fees are collected by the owner of a position\\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\n /// @param owner The owner of the position for which fees are collected\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount0 The amount of token0 fees collected\\n /// @param amount1 The amount of token1 fees collected\\n event Collect(\\n address indexed owner,\\n address recipient,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount0,\\n uint128 amount1\\n );\\n\\n /// @notice Emitted when a position's liquidity is removed\\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\n /// @param owner The owner of the position for which liquidity is removed\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity to remove\\n /// @param amount0 The amount of token0 withdrawn\\n /// @param amount1 The amount of token1 withdrawn\\n event Burn(\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted by the pool for any swaps between token0 and token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the output of the swap\\n /// @param amount0 The delta of the token0 balance of the pool\\n /// @param amount1 The delta of the token1 balance of the pool\\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\n /// @param liquidity The liquidity of the pool after the swap\\n /// @param tick The log base 1.0001 of price of the pool after the swap\\n event Swap(\\n address indexed sender,\\n address indexed recipient,\\n int256 amount0,\\n int256 amount1,\\n uint160 sqrtPriceX96,\\n uint128 liquidity,\\n int24 tick\\n );\\n\\n /// @notice Emitted by the pool for any flashes of token0/token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the tokens from flash\\n /// @param amount0 The amount of token0 that was flashed\\n /// @param amount1 The amount of token1 that was flashed\\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\n event Flash(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1,\\n uint256 paid0,\\n uint256 paid1\\n );\\n\\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\n /// just before a mint/swap/burn.\\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\n event IncreaseObservationCardinalityNext(\\n uint16 observationCardinalityNextOld,\\n uint16 observationCardinalityNextNew\\n );\\n\\n /// @notice Emitted when the protocol fee is changed by the pool\\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\\n /// @param feeProtocol0New The updated value of the token0 protocol fee\\n /// @param feeProtocol1New The updated value of the token1 protocol fee\\n event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\n\\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\n /// @param sender The address that collects the protocol fees\\n /// @param recipient The address that receives the collected protocol fees\\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\\n event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that never changes\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\ninterface IUniswapV3PoolImmutables {\\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\n /// @return The contract address\\n function factory() external view returns (address);\\n\\n /// @notice The first of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token0() external view returns (address);\\n\\n /// @notice The second of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token1() external view returns (address);\\n\\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\n /// @return The fee\\n function fee() external view returns (uint24);\\n\\n /// @notice The pool tick spacing\\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\n /// This value is an int24 to avoid casting even though it is always positive.\\n /// @return The tick spacing\\n function tickSpacing() external view returns (int24);\\n\\n /// @notice The maximum amount of position liquidity that can use any tick in the range\\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\n /// @return The max amount of liquidity per tick\\n function maxLiquidityPerTick() external view returns (uint128);\\n}\\n\",\"keccak256\":\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissioned pool actions\\n/// @notice Contains pool methods that may only be called by the factory owner\\ninterface IUniswapV3PoolOwnerActions {\\n /// @notice Set the denominator of the protocol's % share of the fees\\n /// @param feeProtocol0 new protocol fee for token0 of the pool\\n /// @param feeProtocol1 new protocol fee for token1 of the pool\\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\n\\n /// @notice Collect the protocol fee accrued to the pool\\n /// @param recipient The address to which collected protocol fees should be sent\\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\n /// @return amount0 The protocol fee collected in token0\\n /// @return amount1 The protocol fee collected in token1\\n function collectProtocol(\\n address recipient,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n /// when accessed externally.\\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n /// boundary.\\n /// observationIndex The index of the last oracle observation that was written,\\n /// observationCardinality The current maximum number of observations stored in the pool,\\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n /// feeProtocol The protocol fee for both tokens of the pool.\\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n /// unlocked Whether the pool is currently locked to reentrancy\\n function slot0()\\n external\\n view\\n returns (\\n uint160 sqrtPriceX96,\\n int24 tick,\\n uint16 observationIndex,\\n uint16 observationCardinality,\\n uint16 observationCardinalityNext,\\n uint8 feeProtocol,\\n bool unlocked\\n );\\n\\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n /// @notice The amounts of token0 and token1 that are owed to the protocol\\n /// @dev Protocol fees will never exceed uint128 max in either token\\n function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n /// @notice The currently in range liquidity available to the pool\\n /// @dev This value has no relationship to the total liquidity across all ticks\\n function liquidity() external view returns (uint128);\\n\\n /// @notice Look up information about a specific tick in the pool\\n /// @param tick The tick to look up\\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n /// tick upper,\\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n /// a specific position.\\n function ticks(int24 tick)\\n external\\n view\\n returns (\\n uint128 liquidityGross,\\n int128 liquidityNet,\\n uint256 feeGrowthOutside0X128,\\n uint256 feeGrowthOutside1X128,\\n int56 tickCumulativeOutside,\\n uint160 secondsPerLiquidityOutsideX128,\\n uint32 secondsOutside,\\n bool initialized\\n );\\n\\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n /// @notice Returns the information about a position by the position's key\\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n /// @return _liquidity The amount of liquidity in the position,\\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n function positions(bytes32 key)\\n external\\n view\\n returns (\\n uint128 _liquidity,\\n uint256 feeGrowthInside0LastX128,\\n uint256 feeGrowthInside1LastX128,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n );\\n\\n /// @notice Returns data about a specific observation index\\n /// @param index The element of the observations array to fetch\\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n /// ago, rather than at a specific index in the array.\\n /// @return blockTimestamp The timestamp of the observation,\\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n /// Returns initialized whether the observation has been initialized and the values are safe to use\\n function observations(uint256 index)\\n external\\n view\\n returns (\\n uint32 blockTimestamp,\\n int56 tickCumulative,\\n uint160 secondsPerLiquidityCumulativeX128,\\n bool initialized\\n );\\n}\\n\",\"keccak256\":\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.4.0;\\n\\n/// @title FixedPoint96\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\n/// @dev Used in SqrtPriceMath.sol\\nlibrary FixedPoint96 {\\n uint8 internal constant RESOLUTION = 96;\\n uint256 internal constant Q96 = 0x1000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/FullMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n /// @notice Calculates floor(a\\u00d7b\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n /// @param a The multiplicand\\n /// @param b The multiplier\\n /// @param denominator The divisor\\n /// @return result The 256-bit result\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\n function mulDiv(\\n uint256 a,\\n uint256 b,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = a * b\\n // Compute the product mod 2**256 and mod 2**256 - 1\\n // then use the Chinese Remainder Theorem to reconstruct\\n // 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(a, b, not(0))\\n prod0 := mul(a, b)\\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 require(denominator > 0);\\n assembly {\\n result := div(prod0, denominator)\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2**256.\\n // 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 // Compute remainder using mulmod\\n uint256 remainder;\\n assembly {\\n remainder := mulmod(a, b, denominator)\\n }\\n // Subtract 256 bit number from 512 bit number\\n assembly {\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator\\n // Compute largest power of two divisor of denominator.\\n // Always >= 1.\\n uint256 twos = -denominator & denominator;\\n // Divide denominator by power of two\\n assembly {\\n denominator := div(denominator, twos)\\n }\\n\\n // Divide [prod1 prod0] by the factors of two\\n assembly {\\n prod0 := div(prod0, twos)\\n }\\n // Shift in bits from prod1 into prod0. For this we need\\n // to flip `twos` such that it is 2**256 / twos.\\n // If twos is zero, then it becomes one\\n assembly {\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2**256\\n // Now that denominator is an odd number, it has an inverse\\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n // Compute the inverse by starting with a seed that is correct\\n // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n uint256 inv = (3 * denominator) ^ 2;\\n // Now use Newton-Raphson iteration to improve the precision.\\n // Thanks to Hensel's lifting lemma, this also works in modular\\n // arithmetic, doubling the correct bits in each step.\\n inv *= 2 - denominator * inv; // inverse mod 2**8\\n inv *= 2 - denominator * inv; // inverse mod 2**16\\n inv *= 2 - denominator * inv; // inverse mod 2**32\\n inv *= 2 - denominator * inv; // inverse mod 2**64\\n inv *= 2 - denominator * inv; // inverse mod 2**128\\n inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n // Because the division is now exact we can divide by multiplying\\n // with the modular inverse of denominator. This will give us the\\n // correct result modulo 2**256. Since the precoditions guarantee\\n // that the outcome is less than 2**256, this is the final result.\\n // We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inv;\\n return result;\\n }\\n\\n /// @notice Calculates ceil(a\\u00d7b\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n /// @param a The multiplicand\\n /// @param b The multiplier\\n /// @param denominator The divisor\\n /// @return result The 256-bit result\\n function mulDivRoundingUp(\\n uint256 a,\\n uint256 b,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n result = mulDiv(a, b, denominator);\\n if (mulmod(a, b, denominator) > 0) {\\n require(result < type(uint256).max);\\n result++;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\",\"license\":\"MIT\"},\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n /// @notice Returns x + y, reverts if sum overflows uint256\\n /// @param x The augend\\n /// @param y The addend\\n /// @return z The sum of x and y\\n function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n require((z = x + y) >= x);\\n }\\n\\n /// @notice Returns x - y, reverts if underflows\\n /// @param x The minuend\\n /// @param y The subtrahend\\n /// @return z The difference of x and y\\n function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n require((z = x - y) <= x);\\n }\\n\\n /// @notice Returns x * y, reverts if overflows\\n /// @param x The multiplicand\\n /// @param y The multiplier\\n /// @return z The product of x and y\\n function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n require(x == 0 || (z = x * y) / x == y);\\n }\\n\\n /// @notice Returns x + y, reverts if overflows or underflows\\n /// @param x The augend\\n /// @param y The addend\\n /// @return z The sum of x and y\\n function add(int256 x, int256 y) internal pure returns (int256 z) {\\n require((z = x + y) >= x == (y >= 0));\\n }\\n\\n /// @notice Returns x - y, reverts if overflows or underflows\\n /// @param x The minuend\\n /// @param y The subtrahend\\n /// @return z The difference of x and y\\n function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n require((z = x - y) <= x == (y >= 0));\\n }\\n}\\n\",\"keccak256\":\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Safe casting methods\\n/// @notice Contains methods for safely casting between types\\nlibrary SafeCast {\\n /// @notice Cast a uint256 to a uint160, revert on overflow\\n /// @param y The uint256 to be downcasted\\n /// @return z The downcasted integer, now type uint160\\n function toUint160(uint256 y) internal pure returns (uint160 z) {\\n require((z = uint160(y)) == y);\\n }\\n\\n /// @notice Cast a int256 to a int128, revert on overflow or underflow\\n /// @param y The int256 to be downcasted\\n /// @return z The downcasted integer, now type int128\\n function toInt128(int256 y) internal pure returns (int128 z) {\\n require((z = int128(y)) == y);\\n }\\n\\n /// @notice Cast a uint256 to a int256, revert on overflow\\n /// @param y The uint256 to be casted\\n /// @return z The casted integer, now type int256\\n function toInt256(uint256 y) internal pure returns (int256 z) {\\n require(y < 2**255);\\n z = int256(y);\\n }\\n}\\n\",\"keccak256\":\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/TickMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n int24 internal constant MIN_TICK = -887272;\\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n /// @dev Throws if |tick| > max tick\\n /// @param tick The input tick for the above formula\\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n /// at the given tick\\n function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n require(absTick <= uint256(MAX_TICK), 'T');\\n\\n uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n }\\n\\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n /// ever return.\\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n // second inequality must be < because the price can never reach the price at the max tick\\n require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n uint256 r = ratio;\\n uint256 msb = 0;\\n\\n assembly {\\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(5, gt(r, 0xFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(4, gt(r, 0xFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(3, gt(r, 0xFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(2, gt(r, 0xF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(1, gt(r, 0x3))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := gt(r, 0x1)\\n msb := or(msb, f)\\n }\\n\\n if (msb >= 128) r = ratio >> (msb - 127);\\n else r = ratio << (127 - msb);\\n\\n int256 log_2 = (int256(msb) - 128) << 64;\\n\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(63, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(62, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(61, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(60, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(59, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(58, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(57, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(56, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(55, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(54, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(53, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(52, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(51, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(50, f))\\n }\\n\\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n }\\n}\\n\",\"keccak256\":\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math functions that do not check inputs or outputs\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\nlibrary UnsafeMath {\\n /// @notice Returns ceil(x / y)\\n /// @dev division by 0 has unspecified behavior, and must be checked externally\\n /// @param x The dividend\\n /// @param y The divisor\\n /// @return z The quotient, ceil(x / y)\\n function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n assembly {\\n z := add(div(x, y), gt(mod(x, y), 0))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n /// @notice The permit typehash used in the permit signature\\n /// @return The typehash for the permit\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n /// @notice The domain separator used in the permit signature\\n /// @return The domain seperator used in encoding of permit signature\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n /// @notice Approve of a specific token ID for spending by spender via signature\\n /// @param spender The account that is being approved\\n /// @param tokenId The ID of the token that is being approved for spending\\n /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n function permit(\\n address spender,\\n uint256 tokenId,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external payable;\\n}\\n\",\"keccak256\":\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n IPoolInitializer,\\n IPeripheryPayments,\\n IPeripheryImmutableState,\\n IERC721Metadata,\\n IERC721Enumerable,\\n IERC721Permit\\n{\\n /// @notice Emitted when liquidity is increased for a position NFT\\n /// @dev Also emitted when a token is minted\\n /// @param tokenId The ID of the token for which liquidity was increased\\n /// @param liquidity The amount by which liquidity for the NFT position was increased\\n /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n /// @notice Emitted when liquidity is decreased for a position NFT\\n /// @param tokenId The ID of the token for which liquidity was decreased\\n /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n /// @notice Emitted when tokens are collected for a position NFT\\n /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n /// @param tokenId The ID of the token for which underlying tokens were collected\\n /// @param recipient The address of the account that received the collected tokens\\n /// @param amount0 The amount of token0 owed to the position that was collected\\n /// @param amount1 The amount of token1 owed to the position that was collected\\n event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n /// @notice Returns the position information associated with a given token ID.\\n /// @dev Throws if the token ID is not valid.\\n /// @param tokenId The ID of the token that represents the position\\n /// @return nonce The nonce for permits\\n /// @return operator The address that is approved for spending\\n /// @return token0 The address of the token0 for a specific pool\\n /// @return token1 The address of the token1 for a specific pool\\n /// @return fee The fee associated with the pool\\n /// @return tickLower The lower end of the tick range for the position\\n /// @return tickUpper The higher end of the tick range for the position\\n /// @return liquidity The liquidity of the position\\n /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n function positions(uint256 tokenId)\\n external\\n view\\n returns (\\n uint96 nonce,\\n address operator,\\n address token0,\\n address token1,\\n uint24 fee,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity,\\n uint256 feeGrowthInside0LastX128,\\n uint256 feeGrowthInside1LastX128,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n );\\n\\n struct MintParams {\\n address token0;\\n address token1;\\n uint24 fee;\\n int24 tickLower;\\n int24 tickUpper;\\n uint256 amount0Desired;\\n uint256 amount1Desired;\\n uint256 amount0Min;\\n uint256 amount1Min;\\n address recipient;\\n uint256 deadline;\\n }\\n\\n /// @notice Creates a new position wrapped in a NFT\\n /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n /// a method does not exist, i.e. the pool is assumed to be initialized.\\n /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n /// @return tokenId The ID of the token that represents the minted position\\n /// @return liquidity The amount of liquidity for this position\\n /// @return amount0 The amount of token0\\n /// @return amount1 The amount of token1\\n function mint(MintParams calldata params)\\n external\\n payable\\n returns (\\n uint256 tokenId,\\n uint128 liquidity,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n struct IncreaseLiquidityParams {\\n uint256 tokenId;\\n uint256 amount0Desired;\\n uint256 amount1Desired;\\n uint256 amount0Min;\\n uint256 amount1Min;\\n uint256 deadline;\\n }\\n\\n /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n /// @param params tokenId The ID of the token for which liquidity is being increased,\\n /// amount0Desired The desired amount of token0 to be spent,\\n /// amount1Desired The desired amount of token1 to be spent,\\n /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n /// deadline The time by which the transaction must be included to effect the change\\n /// @return liquidity The new liquidity amount as a result of the increase\\n /// @return amount0 The amount of token0 to acheive resulting liquidity\\n /// @return amount1 The amount of token1 to acheive resulting liquidity\\n function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n external\\n payable\\n returns (\\n uint128 liquidity,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n struct DecreaseLiquidityParams {\\n uint256 tokenId;\\n uint128 liquidity;\\n uint256 amount0Min;\\n uint256 amount1Min;\\n uint256 deadline;\\n }\\n\\n /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n /// amount The amount by which liquidity will be decreased,\\n /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n /// deadline The time by which the transaction must be included to effect the change\\n /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n external\\n payable\\n returns (uint256 amount0, uint256 amount1);\\n\\n struct CollectParams {\\n uint256 tokenId;\\n address recipient;\\n uint128 amount0Max;\\n uint128 amount1Max;\\n }\\n\\n /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n /// recipient The account that should receive the tokens,\\n /// amount0Max The maximum amount of token0 to collect,\\n /// amount1Max The maximum amount of token1 to collect\\n /// @return amount0 The amount of fees collected in token0\\n /// @return amount1 The amount of fees collected in token1\\n function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n /// must be collected first.\\n /// @param tokenId The ID of the token that is being burned\\n function burn(uint256 tokenId) external payable;\\n}\\n\",\"keccak256\":\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n /// @return Returns the address of the Uniswap V3 factory\\n function factory() external view returns (address);\\n\\n /// @return Returns the address of WETH9\\n function WETH9() external view returns (address);\\n}\\n\",\"keccak256\":\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n /// @param recipient The address receiving ETH\\n function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n /// that use ether for the input amount\\n function refundETH() external payable;\\n\\n /// @notice Transfers the full amount of a token held by this contract to recipient\\n /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n /// @param token The contract address of the token which will be transferred to `recipient`\\n /// @param amountMinimum The minimum amount of token required for a transfer\\n /// @param recipient The destination address of the token\\n function sweepToken(\\n address token,\\n uint256 amountMinimum,\\n address recipient\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n /// @param token0 The contract address of token0 of the pool\\n /// @param token1 The contract address of token1 of the pool\\n /// @param fee The fee amount of the v3 pool for the specified token pair\\n /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n function createAndInitializePoolIfNecessary(\\n address token0,\\n address token1,\\n uint24 fee,\\n uint160 sqrtPriceX96\\n ) external payable returns (address pool);\\n}\\n\",\"keccak256\":\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gon\\u00e7alo S\\u00e1 \\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n require(_length + 31 >= _length, 'slice_overflow');\\n require(_start + _length >= _start, 'slice_overflow');\\n require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n require(_start + 20 >= _start, 'toAddress_overflow');\\n require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n }\\n\\n return tempAddress;\\n }\\n\\n function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n require(_start + 3 >= _start, 'toUint24_overflow');\\n require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n uint24 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0x3), _start))\\n }\\n\\n return tempUint;\\n }\\n}\\n\",\"keccak256\":\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n /// @notice Returns the address of a valid Uniswap V3 Pool\\n /// @param factory The contract address of the Uniswap V3 factory\\n /// @param tokenA The contract address of either token0 or token1\\n /// @param tokenB The contract address of the other token\\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n /// @return pool The V3 pool contract address\\n function verifyCallback(\\n address factory,\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n ) internal view returns (IUniswapV3Pool pool) {\\n return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n }\\n\\n /// @notice Returns the address of a valid Uniswap V3 Pool\\n /// @param factory The contract address of the Uniswap V3 factory\\n /// @param poolKey The identifying key of the V3 pool\\n /// @return pool The V3 pool contract address\\n function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n internal\\n view\\n returns (IUniswapV3Pool pool)\\n {\\n pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n require(msg.sender == address(pool));\\n }\\n}\\n\",\"keccak256\":\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/libraries/Path.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n using BytesLib for bytes;\\n\\n /// @dev The length of the bytes encoded address\\n uint256 private constant ADDR_SIZE = 20;\\n /// @dev The length of the bytes encoded fee\\n uint256 private constant FEE_SIZE = 3;\\n\\n /// @dev The offset of a single token address and pool fee\\n uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n /// @dev The offset of an encoded pool key\\n uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n /// @dev The minimum length of an encoding that contains 2 or more pools\\n uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n /// @notice Returns true iff the path contains two or more pools\\n /// @param path The encoded swap path\\n /// @return True if path contains two or more pools, otherwise false\\n function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n }\\n\\n /// @notice Returns the number of pools in the path\\n /// @param path The encoded swap path\\n /// @return The number of pools in the path\\n function numPools(bytes memory path) internal pure returns (uint256) {\\n // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n }\\n\\n /// @notice Decodes the first pool in path\\n /// @param path The bytes encoded swap path\\n /// @return tokenA The first token of the given pool\\n /// @return tokenB The second token of the given pool\\n /// @return fee The fee level of the pool\\n function decodeFirstPool(bytes memory path)\\n internal\\n pure\\n returns (\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n )\\n {\\n tokenA = path.toAddress(0);\\n fee = path.toUint24(ADDR_SIZE);\\n tokenB = path.toAddress(NEXT_OFFSET);\\n }\\n\\n /// @notice Gets the segment corresponding to the first pool in the path\\n /// @param path The bytes encoded swap path\\n /// @return The segment containing all data necessary to target the first pool in the path\\n function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n return path.slice(0, POP_OFFSET);\\n }\\n\\n /// @notice Skips a token + fee element from the buffer and returns the remainder\\n /// @param path The swap path\\n /// @return The remaining token + fee elements in the path\\n function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n }\\n}\\n\",\"keccak256\":\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n /// @notice The identifying key of the pool\\n struct PoolKey {\\n address token0;\\n address token1;\\n uint24 fee;\\n }\\n\\n /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n /// @param tokenA The first token of a pool, unsorted\\n /// @param tokenB The second token of a pool, unsorted\\n /// @param fee The fee level of the pool\\n /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n function getPoolKey(\\n address tokenA,\\n address tokenB,\\n uint24 fee\\n ) internal pure returns (PoolKey memory) {\\n if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n }\\n\\n /// @notice Deterministically computes the pool address given the factory and PoolKey\\n /// @param factory The Uniswap V3 factory contract address\\n /// @param key The PoolKey\\n /// @return pool The contract address of the V3 pool\\n function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n require(key.token0 < key.token1);\\n pool = address(\\n uint256(\\n keccak256(\\n abi.encodePacked(\\n hex'ff',\\n factory,\\n keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n POOL_INIT_CODE_HASH\\n )\\n )\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n function ethQuoteCurrencyPool() external view returns (address);\\n\\n function feeRate() external view returns (uint256);\\n\\n function getFee(\\n uint256 _vaultId,\\n uint256 _wPowerPerpAmount,\\n uint256 _collateralAmount\\n ) external view returns (uint256);\\n\\n function quoteCurrency() external view returns (address);\\n\\n function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n function shortPowerPerp() external view returns (address);\\n\\n function wPowerPerp() external view returns (address);\\n\\n function wPowerPerpPool() external view returns (address);\\n\\n function oracle() external view returns (address);\\n\\n function weth() external view returns (address);\\n\\n function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n function mintPowerPerpAmount(\\n uint256 _vaultId,\\n uint256 _powerPerpAmount,\\n uint256 _uniTokenId\\n ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n function mintWPowerPerpAmount(\\n uint256 _vaultId,\\n uint256 _wPowerPerpAmount,\\n uint256 _uniTokenId\\n ) external payable returns (uint256 vaultId);\\n\\n /**\\n * Deposit collateral into a vault\\n */\\n function deposit(uint256 _vaultId) external payable;\\n\\n /**\\n * Withdraw collateral from a vault.\\n */\\n function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n function burnWPowerPerpAmount(\\n uint256 _vaultId,\\n uint256 _wPowerPerpAmount,\\n uint256 _withdrawAmount\\n ) external;\\n\\n function burnPowerPerpAmount(\\n uint256 _vaultId,\\n uint256 _powerPerpAmount,\\n uint256 _withdrawAmount\\n ) external returns (uint256 wPowerPerpAmount);\\n\\n function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n /**\\n * External function to update the normalized factor as a way to pay funding.\\n */\\n function applyFunding() external;\\n\\n function redeemShort(uint256 _vaultId) external;\\n\\n function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n function isShutDown() external returns (bool);\\n\\n function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\",\"keccak256\":\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Detailed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\",\"license\":\"MIT\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n function getHistoricalTwap(\\n address _pool,\\n address _base,\\n address _quote,\\n uint32 _period,\\n uint32 _periodToHistoricPrice\\n ) external view returns (uint256);\\n\\n function getTwap(\\n address _pool,\\n address _base,\\n address _quote,\\n uint32 _period,\\n bool _checkPeriod\\n ) external view returns (uint256);\\n\\n function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n external\\n view\\n returns (int24 timeWeightedAverageTick);\\n}\\n\",\"keccak256\":\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\",\"license\":\"MIT\"},\"contracts/interfaces/IShortPowerPerp.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n function nextId() external view returns (uint256);\\n\\n function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\",\"keccak256\":\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\",\"license\":\"MIT\"},\"contracts/interfaces/IWETH9.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n function deposit() external payable;\\n\\n function withdraw(uint256 wad) external;\\n}\\n\",\"keccak256\":\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\",\"license\":\"MIT\"},\"contracts/interfaces/IWPowerPerp.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n function mint(address _account, uint256 _amount) external;\\n\\n function burn(address _account, uint256 _amount) external;\\n}\\n\",\"keccak256\":\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\",\"license\":\"MIT\"},\"contracts/libs/SqrtPriceMathPartial.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n /// @notice Gets the amount0 delta between two prices\\n /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n /// @param sqrtRatioAX96 A sqrt price\\n /// @param sqrtRatioBX96 Another sqrt price\\n /// @param liquidity The amount of usable liquidity\\n /// @param roundUp Whether to round the amount up or down\\n /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n function getAmount0Delta(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity,\\n bool roundUp\\n ) external pure returns (uint256 amount0) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n require(sqrtRatioAX96 > 0);\\n\\n return\\n roundUp\\n ? UnsafeMath.divRoundingUp(\\n FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n sqrtRatioAX96\\n )\\n : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n }\\n\\n /// @notice Gets the amount1 delta between two prices\\n /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n /// @param sqrtRatioAX96 A sqrt price\\n /// @param sqrtRatioBX96 Another sqrt price\\n /// @param liquidity The amount of usable liquidity\\n /// @param roundUp Whether to round the amount up, or down\\n /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n function getAmount1Delta(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity,\\n bool roundUp\\n ) external pure returns (uint256 amount1) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n return\\n roundUp\\n ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n }\\n}\\n\",\"keccak256\":\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libs/TickMathExternal.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n int24 internal constant MIN_TICK = -887272;\\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n /// @dev Throws if |tick| > max tick\\n /// @param tick The input tick for the above formula\\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n /// at the given tick\\n function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n }\\n\\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n /// ever return.\\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n // second inequality must be < because the price can never reach the price at the max tick\\n require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n uint256 r = ratio;\\n uint256 msb = 0;\\n\\n assembly {\\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(5, gt(r, 0xFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(4, gt(r, 0xFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(3, gt(r, 0xFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(2, gt(r, 0xF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(1, gt(r, 0x3))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := gt(r, 0x1)\\n msb := or(msb, f)\\n }\\n\\n if (msb >= 128) r = ratio >> (msb - 127);\\n else r = ratio << (127 - msb);\\n\\n int256 log_2 = (int256(msb) - 128) << 64;\\n\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(63, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(62, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(61, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(60, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(59, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(58, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(57, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(56, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(55, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(54, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(53, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(52, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(51, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(50, f))\\n }\\n\\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n }\\n}\\n\",\"keccak256\":\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libs/Uint256Casting.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n /**\\n * @notice cast a uint256 to a uint128, revert on overflow\\n * @param y the uint256 to be downcasted\\n * @return z the downcasted integer, now type uint128\\n */\\n function toUint128(uint256 y) internal pure returns (uint128 z) {\\n require((z = uint128(y)) == y, \\\"OF128\\\");\\n }\\n\\n /**\\n * @notice cast a uint256 to a uint96, revert on overflow\\n * @param y the uint256 to be downcasted\\n * @return z the downcasted integer, now type uint96\\n */\\n function toUint96(uint256 y) internal pure returns (uint96 z) {\\n require((z = uint96(y)) == y, \\\"OF96\\\");\\n }\\n\\n /**\\n * @notice cast a uint256 to a uint32, revert on overflow\\n * @param y the uint256 to be downcasted\\n * @return z the downcasted integer, now type uint32\\n */\\n function toUint32(uint256 y) internal pure returns (uint32 z) {\\n require((z = uint32(y)) == y, \\\"OF32\\\");\\n }\\n}\\n\",\"keccak256\":\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\",\"license\":\"MIT\"},\"contracts/libs/VaultLib.sol\":{\"content\":\"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n using SafeMath for uint256;\\n using Uint256Casting for uint256;\\n\\n uint256 constant ONE_ONE = 1e36;\\n\\n // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n uint256 public constant CR_NUMERATOR = 3;\\n uint256 public constant CR_DENOMINATOR = 2;\\n\\n struct Vault {\\n // the address that can update the vault\\n address operator;\\n // uniswap position token id deposited into the vault as collateral\\n // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n uint32 NftCollateralId;\\n // amount of eth (wei) used in the vault as collateral\\n // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n uint96 collateralAmount;\\n // amount of wPowerPerp minted from the vault\\n uint128 shortAmount;\\n }\\n\\n /**\\n * @notice add eth collateral to a vault\\n * @param _vault in-memory vault\\n * @param _amount amount of eth to add\\n */\\n function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n }\\n\\n /**\\n * @notice add uniswap position token collateral to a vault\\n * @param _vault in-memory vault\\n * @param _tokenId uniswap position token id\\n */\\n function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n require(_tokenId != 0, \\\"C23\\\");\\n _vault.NftCollateralId = _tokenId.toUint32();\\n }\\n\\n /**\\n * @notice remove eth collateral from a vault\\n * @param _vault in-memory vault\\n * @param _amount amount of eth to remove\\n */\\n function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n }\\n\\n /**\\n * @notice remove uniswap position token collateral from a vault\\n * @param _vault in-memory vault\\n */\\n function removeUniNftCollateral(Vault memory _vault) internal pure {\\n require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n _vault.NftCollateralId = 0;\\n }\\n\\n /**\\n * @notice add debt to vault\\n * @param _vault in-memory vault\\n * @param _amount amount of debt to add\\n */\\n function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n }\\n\\n /**\\n * @notice remove debt from vault\\n * @param _vault in-memory vault\\n * @param _amount amount of debt to remove\\n */\\n function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n }\\n\\n /**\\n * @notice check if a vault is properly collateralized\\n * @param _vault the vault we want to check\\n * @param _positionManager address of the uniswap position manager\\n * @param _normalizationFactor current _normalizationFactor\\n * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n * @param _minCollateral minimum collateral that needs to be in a vault\\n * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n * @return true if the vault is sufficiently collateralized\\n * @return true if the vault is considered as a dust vault\\n */\\n function getVaultStatus(\\n Vault memory _vault,\\n address _positionManager,\\n uint256 _normalizationFactor,\\n uint256 _ethQuoteCurrencyPrice,\\n uint256 _minCollateral,\\n int24 _wsqueethPoolTick,\\n bool _isWethToken0\\n ) internal view returns (bool, bool) {\\n if (_vault.shortAmount == 0) return (true, false);\\n\\n uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n ONE_ONE\\n );\\n uint256 totalCollateral = _getEffectiveCollateral(\\n _vault,\\n _positionManager,\\n _normalizationFactor,\\n _ethQuoteCurrencyPrice,\\n _wsqueethPoolTick,\\n _isWethToken0\\n );\\n\\n bool isDust = totalCollateral < _minCollateral;\\n bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n return (isAboveWater, isDust);\\n }\\n\\n /**\\n * @notice get the total effective collateral of a vault, which is:\\n * collateral amount + uniswap position token equivelent amount in eth\\n * @param _vault the vault we want to check\\n * @param _positionManager address of the uniswap position manager\\n * @param _normalizationFactor current _normalizationFactor\\n * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n * @return the total worth of collateral in the vault\\n */\\n function _getEffectiveCollateral(\\n Vault memory _vault,\\n address _positionManager,\\n uint256 _normalizationFactor,\\n uint256 _ethQuoteCurrencyPrice,\\n int24 _wsqueethPoolTick,\\n bool _isWethToken0\\n ) internal view returns (uint256) {\\n if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n _positionManager,\\n _vault.NftCollateralId,\\n _wsqueethPoolTick,\\n _isWethToken0\\n );\\n // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n ONE_ONE\\n );\\n // add eth value from uniswap position token as collateral\\n return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n }\\n\\n /**\\n * @notice determine how much eth / wPowerPerp the uniswap position contains\\n * @param _positionManager address of the uniswap position manager\\n * @param _tokenId uniswap position token id\\n * @param _wPowerPerpPoolTick current price tick\\n * @param _isWethToken0 whether weth is token0 in the pool\\n * @return ethAmount the eth amount this LP token contains\\n * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n */\\n function _getUniPositionBalances(\\n address _positionManager,\\n uint256 _tokenId,\\n int24 _wPowerPerpPoolTick,\\n bool _isWethToken0\\n ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n (\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n tickLower,\\n tickUpper,\\n _wPowerPerpPoolTick,\\n liquidity\\n );\\n\\n return\\n _isWethToken0\\n ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n }\\n\\n /**\\n * @notice get uniswap position token info\\n * @param _positionManager address of the uniswap position position manager\\n * @param _tokenId uniswap position token id\\n * @return tickLower lower tick of the position\\n * @return tickUpper upper tick of the position\\n * @return liquidity raw liquidity amount of the position\\n * @return tokensOwed0 amount of token 0 can be collected as fee\\n * @return tokensOwed1 amount of token 1 can be collected as fee\\n */\\n function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n internal\\n view\\n returns (\\n int24,\\n int24,\\n uint128,\\n uint128,\\n uint128\\n )\\n {\\n INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n (\\n ,\\n ,\\n ,\\n ,\\n ,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity,\\n ,\\n ,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n ) = positionManager.positions(_tokenId);\\n return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n }\\n\\n /**\\n * @notice get balances of token0 / token1 in a uniswap position\\n * @dev knowing liquidity, tick range, and current tick gives balances\\n * @param _tickLower address of the uniswap position manager\\n * @param _tickUpper uniswap position token id\\n * @param _tick current price tick used for calculation\\n * @return amount0 the amount of token0 in the uniswap position token\\n * @return amount1 the amount of token1 in the uniswap position token\\n */\\n function _getToken0Token1Balances(\\n int24 _tickLower,\\n int24 _tickUpper,\\n int24 _tick,\\n uint128 _liquidity\\n ) internal pure returns (uint256 amount0, uint256 amount1) {\\n // get the current price and tick from wPowerPerp pool\\n uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n if (_tick < _tickLower) {\\n amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n _liquidity,\\n true\\n );\\n } else if (_tick < _tickUpper) {\\n amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n sqrtPriceX96,\\n TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n _liquidity,\\n true\\n );\\n amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n sqrtPriceX96,\\n _liquidity,\\n true\\n );\\n } else {\\n amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n _liquidity,\\n true\\n );\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\",\"license\":\"GPL-2.0-or-later\"},\"contracts/periphery/ControllerHelper.sol\":{\"content\":\"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n using SafeMath for uint256;\\n using Address for address payable;\\n\\n bool private immutable isWethToken0;\\n address private immutable controller;\\n address private immutable shortPowerPerp;\\n address private immutable wPowerPerp;\\n address private immutable weth;\\n address private immutable nonfungiblePositionManager;\\n\\n constructor(\\n address _controller,\\n address _nonfungiblePositionManager,\\n address _uniswapFactory,\\n address _exec,\\n address _euler,\\n address _dToken\\n )\\n UniswapControllerHelper(_uniswapFactory)\\n EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n {\\n controller = _controller;\\n shortPowerPerp = IController(_controller).shortPowerPerp();\\n wPowerPerp = IController(_controller).wPowerPerp();\\n weth = IController(_controller).weth();\\n nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n }\\n\\n /**\\n * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n * @return returns received selector\\n */\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n\\n /**\\n * @notice receive function to allow ETH transfer to this contract\\n */\\n receive() external payable {}\\n\\n /**\\n * @notice flash close position and buy long squeeth\\n * @dev this function\\n * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n */\\n function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n external\\n payable\\n {\\n _checkAccess(_params.vaultId);\\n\\n require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n wrapInternal(msg.value);\\n\\n _exactOutFlashSwap(\\n weth,\\n wPowerPerp,\\n _params.poolFee,\\n _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n _params.maxToPay,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n abi.encode(_params)\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice sell long wPowerPerp and flashswap mint short position\\n * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n */\\n function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n external\\n payable\\n {\\n if (_params.vaultId != 0) {\\n _checkAccess(_params.vaultId);\\n }\\n\\n wrapInternal(msg.value);\\n IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n // flashswap and mint short position\\n uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n _exactInFlashSwap(\\n wPowerPerp,\\n weth,\\n _params.poolFee,\\n totalAmountIn,\\n _params.minToReceive,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n abi.encode(_params)\\n );\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice close short position with user Uniswap v3 LP NFT\\n * @dev user should approve this contract for Uni NFT transfer\\n * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n */\\n function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n external\\n payable\\n {\\n _checkAccess(_params.vaultId);\\n\\n INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _params.tokenId\\n );\\n\\n wrapInternal(msg.value);\\n\\n // close LP position\\n (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: _params.tokenId,\\n liquidity: _params.liquidity,\\n liquidityPercentage: _params.liquidityPercentage,\\n amount0Min: _params.amount0Min,\\n amount1Min: _params.amount1Min\\n }),\\n isWethToken0\\n );\\n\\n // if LP position is not fully closed, redeposit in vault or send back to user\\n ControllerHelperUtil.checkClosedLp(\\n msg.sender,\\n controller,\\n nonfungiblePositionManager,\\n 0,\\n _params.tokenId,\\n _params.liquidityPercentage\\n );\\n // burn vault debt using amounts withdrawn from LP position\\n _closeShortWithAmountsFromLp(\\n _params.vaultId,\\n wPowerPerpAmountInLp,\\n _params.wPowerPerpAmountToBurn,\\n _params.collateralToWithdraw,\\n _params.limitPriceEthPerPowerPerp,\\n _params.poolFee,\\n _params.burnExactRemoved\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n external\\n payable\\n {\\n _checkAccess(_params.vaultId);\\n\\n wrapInternal(msg.value);\\n _flashLoan(\\n weth,\\n _params.collateralToFlashloan,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n abi.encode(_params)\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n * @param _params ControllerHelperDataType.MintAndLpParams struct\\n */\\n function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n if (_params.vaultId != 0) {\\n _checkAccess(_params.vaultId);\\n }\\n require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n wrapInternal(msg.value);\\n\\n (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n controller,\\n nonfungiblePositionManager,\\n wPowerPerp,\\n weth,\\n _params,\\n isWethToken0\\n );\\n\\n // if openeded new vault, transfer vault NFT to user\\n if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n */\\n function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n external\\n payable\\n {\\n if (_params.vaultId != 0) {\\n _checkAccess(_params.vaultId);\\n }\\n\\n wrapInternal(msg.value);\\n _flashLoan(\\n weth,\\n _params.collateralToFlashloan,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n abi.encode(_params)\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n */\\n function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _params.tokenId\\n );\\n\\n // close LP NFT and get Weth and WPowerPerp amounts\\n (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: _params.tokenId,\\n liquidity: _params.liquidity,\\n liquidityPercentage: _params.liquidityPercentage,\\n amount0Min: uint128(_params.amount0Min),\\n amount1Min: uint128(_params.amount1Min)\\n }),\\n isWethToken0\\n );\\n\\n ControllerHelperUtil.checkClosedLp(\\n msg.sender,\\n controller,\\n nonfungiblePositionManager,\\n 0,\\n _params.tokenId,\\n _params.liquidityPercentage\\n );\\n\\n if (wPowerPerpAmountInLp > 0) {\\n _exactInFlashSwap(\\n wPowerPerp,\\n weth,\\n _params.poolFee,\\n wPowerPerpAmountInLp,\\n _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n \\\"\\\"\\n );\\n }\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice Rebalance LP nft through trading\\n * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n */\\n function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n external\\n payable\\n {\\n wrapInternal(msg.value);\\n INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _params.tokenId\\n );\\n // close LP NFT and get Weth and WPowerPerp amounts\\n (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: _params.tokenId,\\n liquidity: _params.liquidity,\\n liquidityPercentage: 1e18,\\n amount0Min: uint128(_params.amount0Min),\\n amount1Min: uint128(_params.amount1Min)\\n }),\\n isWethToken0\\n );\\n\\n ControllerHelperUtil.checkClosedLp(\\n msg.sender,\\n controller,\\n nonfungiblePositionManager,\\n 0,\\n _params.tokenId,\\n 1e18\\n );\\n\\n uint256 wethAmountDesired;\\n uint256 wPowerPerpAmountDesired;\\n\\n if (isWethToken0) {\\n (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n _params.wPowerPerpPool,\\n _params.wethAmountDesired,\\n _params.wPowerPerpAmountDesired,\\n _params.lowerTick,\\n _params.upperTick,\\n isWethToken0\\n );\\n } else {\\n (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n _params.wPowerPerpPool,\\n _params.wethAmountDesired,\\n _params.wPowerPerpAmountDesired,\\n _params.lowerTick,\\n _params.upperTick,\\n isWethToken0\\n );\\n }\\n\\n if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n _exactOutFlashSwap(\\n weth,\\n wPowerPerp,\\n _params.poolFee,\\n wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n \\\"\\\"\\n );\\n } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n _exactInFlashSwap(\\n wPowerPerp,\\n weth,\\n _params.poolFee,\\n wPowerPerpExcess,\\n _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n \\\"\\\"\\n );\\n }\\n\\n // mint new position\\n ControllerHelperUtil.lpWPowerPerpPool(\\n nonfungiblePositionManager,\\n _params.wPowerPerpPool,\\n ControllerHelperDataType.LpWPowerPerpPoolParams({\\n recipient: msg.sender,\\n amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n amount0Min: _params.amount0DesiredMin,\\n amount1Min: _params.amount1DesiredMin,\\n lowerTick: _params.lowerTick,\\n upperTick: _params.upperTick\\n })\\n );\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n * @param _vaultId vault ID\\n * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n */\\n function rebalanceLpInVault(\\n uint256 _vaultId,\\n uint256 _collateralToFlashloan,\\n ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n ) external payable {\\n // check ownership\\n _checkAccess(_vaultId);\\n\\n wrapInternal(msg.value);\\n _flashLoan(\\n weth,\\n _collateralToFlashloan,\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n abi.encode(_vaultId, _params)\\n );\\n\\n require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n }\\n\\n /**\\n * @notice checks if the msg.sender is the owener of the vault\\n * @param _vaultId vault ID\\n */\\n function _checkAccess(uint256 _vaultId) internal view {\\n require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n }\\n\\n /**\\n * @notice gets the shortAmount that has been minted from a vault\\n * @param _vaultId vault ID\\n * @return short amount from vault\\n */\\n\\n function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n return vault.shortAmount;\\n }\\n\\n function _flashCallback(\\n address _initiator,\\n address, /*_asset*/\\n uint256 _amount,\\n uint8 _callSource,\\n bytes memory _calldata\\n ) internal override {\\n if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n ) {\\n ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n _calldata,\\n (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n );\\n\\n (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n controller,\\n nonfungiblePositionManager,\\n wPowerPerp,\\n weth,\\n ControllerHelperDataType.MintAndLpParams({\\n recipient: address(this),\\n wPowerPerpPool: data.wPowerPerpPool,\\n vaultId: data.vaultId,\\n wPowerPerpAmount: data.wPowerPerpAmount,\\n collateralToDeposit: data.collateralToDeposit,\\n collateralToLp: data.collateralToLp,\\n amount0Min: data.amount0Min,\\n amount1Min: data.amount1Min,\\n lowerTick: data.lowerTick,\\n upperTick: data.upperTick\\n }),\\n isWethToken0\\n );\\n\\n // deposit Uni NFT token in vault\\n IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n vaultId,\\n 0,\\n _amount.add(data.collateralToWithdraw)\\n );\\n\\n // if openeded new vault, transfer vault NFT to user\\n if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n ) {\\n ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n _calldata,\\n (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n );\\n\\n IWETH9(weth).withdraw(_amount);\\n IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: data.tokenId,\\n liquidity: data.liquidity,\\n liquidityPercentage: data.liquidityPercentage,\\n amount0Min: data.amount0Min,\\n amount1Min: data.amount1Min\\n }),\\n isWethToken0\\n );\\n\\n ControllerHelperUtil.checkClosedLp(\\n _initiator,\\n controller,\\n nonfungiblePositionManager,\\n data.vaultId,\\n data.tokenId,\\n data.liquidityPercentage\\n );\\n\\n // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n _closeShortWithAmountsFromLp(\\n data.vaultId,\\n wPowerPerpAmountInLp,\\n data.wPowerPerpAmountToBurn,\\n data.collateralToWithdraw.add(data.collateralToFlashloan),\\n data.limitPriceEthPerPowerPerp,\\n data.poolFee,\\n data.burnExactRemoved\\n );\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n ) {\\n (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n _calldata,\\n (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n );\\n\\n // deposit collateral into vault and withdraw LP NFT\\n IWETH9(weth).withdraw(_amount);\\n IController(controller).deposit{value: _amount}(vaultId);\\n IController(controller).withdrawUniPositionToken(vaultId);\\n for (uint256 i; i < data.length; i++) {\\n if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n ) {\\n // increase liquidity in LP position, this can mint wPowerPerp and increase\\n ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n );\\n\\n ControllerHelperUtil.increaseLpLiquidity(\\n controller,\\n nonfungiblePositionManager,\\n wPowerPerp,\\n increaseLiquidityParam.wPowerPerpPool,\\n vaultId,\\n increaseLiquidityParam,\\n isWethToken0\\n );\\n\\n IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n ) {\\n // decrease liquidity in LP\\n ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n );\\n\\n ControllerHelperUtil.closeUniLp(\\n nonfungiblePositionManager,\\n ControllerHelperDataType.CloseUniLpParams({\\n tokenId: decreaseLiquidityParam.tokenId,\\n liquidity: decreaseLiquidityParam.liquidity,\\n liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n amount0Min: decreaseLiquidityParam.amount0Min,\\n amount1Min: decreaseLiquidityParam.amount1Min\\n }),\\n isWethToken0\\n );\\n\\n // if LP position is not fully closed, redeposit into vault or send back to user\\n ControllerHelperUtil.checkClosedLp(\\n _initiator,\\n controller,\\n nonfungiblePositionManager,\\n vaultId,\\n decreaseLiquidityParam.tokenId,\\n decreaseLiquidityParam.liquidityPercentage\\n );\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n ) {\\n ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.DepositIntoVaultParams)\\n );\\n\\n // make sure not to fail\\n // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n ControllerHelperUtil.mintDepositInVault(\\n controller,\\n weth,\\n vaultId,\\n depositIntoVaultParams.wPowerPerpToMint,\\n depositIntoVaultParams.collateralToDeposit\\n );\\n } else if (\\n // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n ) {\\n ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.withdrawFromVaultParams)\\n );\\n\\n uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n if (withdrawFromVaultParams.burnExactRemoved) {\\n uint256 shortAmount = _getVaultShortAmount(vaultId);\\n if (shortAmount < currentBalance) currentBalance = shortAmount;\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n vaultId,\\n currentBalance,\\n withdrawFromVaultParams.collateralToWithdraw\\n );\\n } else {\\n if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n vaultId,\\n withdrawFromVaultParams.wPowerPerpToBurn,\\n withdrawFromVaultParams.collateralToWithdraw\\n );\\n }\\n } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n // this will execute in the use case of fully closing old LP position, and creating new one\\n ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.MintAndLpParams)\\n );\\n\\n uint256 tokenId;\\n (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n controller,\\n nonfungiblePositionManager,\\n wPowerPerp,\\n weth,\\n mintAndLpParams,\\n isWethToken0\\n );\\n // deposit Uni NFT token in vault\\n IController(controller).depositUniPositionToken(vaultId, tokenId);\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n ) {\\n ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.GeneralSwapParams)\\n );\\n\\n require(\\n (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n );\\n\\n _exactInFlashSwap(\\n swapParams.tokenIn,\\n swapParams.tokenOut,\\n swapParams.poolFee,\\n swapParams.amountIn,\\n swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n \\\"\\\"\\n );\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n ) {\\n ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.CollectFeesParams)\\n );\\n\\n INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n .CollectParams({\\n tokenId: collectFeesParams.tokenId,\\n recipient: address(this),\\n amount0Max: collectFeesParams.amount0Max,\\n amount1Max: collectFeesParams.amount0Max\\n });\\n\\n INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n } else if (\\n data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n ) {\\n ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n data[i].data,\\n (ControllerHelperDataType.DepositExistingNftParams)\\n );\\n\\n IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n }\\n }\\n\\n // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n }\\n }\\n\\n /**\\n * @notice uniswap flash swap callback function\\n * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n * @param _caller address of original function caller\\n * @param _amountToPay amount to pay back for flashswap\\n * @param _callData arbitrary data attached to callback\\n * @param _callSource identifier for which function triggered callback\\n */\\n function _swapCallback(\\n address _caller,\\n address _tokenIn,\\n address _pool,\\n uint256 _amountToPay,\\n bytes memory _callData,\\n uint8 _callSource\\n ) internal override {\\n if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n ) {\\n ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n _callData,\\n (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n );\\n\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n data.vaultId,\\n data.wPowerPerpAmountToBurn,\\n data.collateralToWithdraw\\n );\\n\\n IWETH9(weth).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n ) {\\n ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n _callData,\\n (ControllerHelperDataType.FlashSellLongWMintParams)\\n );\\n\\n if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n controller,\\n weth,\\n data.vaultId,\\n data.wPowerPerpAmountToMint,\\n data.collateralToDeposit\\n );\\n\\n // this is a newly open vault, transfer to the user\\n if (data.vaultId == 0)\\n IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n }\\n\\n IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n ) {\\n IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n ) {\\n IWETH9(weth).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n ) {\\n ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n _callData,\\n (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n );\\n\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n data.vaultId,\\n data.wPowerPerpAmountToBurn,\\n data.collateralToWithdraw\\n );\\n\\n IWETH9(weth).transfer(_pool, _amountToPay);\\n } else if (\\n ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n ) {\\n IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n }\\n }\\n\\n /**\\n * @notice wrap ETH to WETH\\n * @param _amount amount to wrap\\n */\\n function wrapInternal(uint256 _amount) internal {\\n if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n }\\n\\n function _closeShortWithAmountsFromLp(\\n uint256 _vaultId,\\n uint256 _wPowerPerpAmount,\\n uint256 _wPowerPerpAmountToBurn,\\n uint256 _collateralToWithdraw,\\n uint256 _limitPriceEthPerPowerPerp,\\n uint24 _poolFee,\\n bool burnExactRemoved\\n ) private {\\n if (burnExactRemoved) {\\n // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n _vaultId,\\n _wPowerPerpAmount,\\n _collateralToWithdraw\\n );\\n } else {\\n if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n // swap needed wPowerPerp amount to close short position\\n uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n _exactOutFlashSwap(\\n weth,\\n wPowerPerp,\\n _poolFee,\\n wPowerPerpDeficit,\\n _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n );\\n } else {\\n // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n ControllerHelperUtil.burnWithdrawFromVault(\\n controller,\\n weth,\\n _vaultId,\\n _wPowerPerpAmountToBurn,\\n _collateralToWithdraw\\n );\\n\\n uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n if (wPowerPerpExcess > 0) {\\n _exactInFlashSwap(\\n wPowerPerp,\\n weth,\\n _poolFee,\\n wPowerPerpExcess,\\n _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n \\\"\\\"\\n );\\n }\\n }\\n }\\n\\n // wrap ETH to WETH\\n wrapInternal(address(this).balance);\\n }\\n}\\n\",\"keccak256\":\"0xe9649979188ed6661ec0511b25ef05748ae61abd4ffc1f716ca7e89b7faf333e\",\"license\":\"BUSL-1.1\"},\"contracts/periphery/EulerControllerHelper.sol\":{\"content\":\"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n using SafeMath for uint256;\\n\\n address public immutable exec;\\n address public immutable euler;\\n address public immutable token;\\n address public immutable dToken;\\n\\n struct FlashloanCallbackData {\\n address caller;\\n address assetToBorrow;\\n uint256 amountToBorrow;\\n uint8 callSource;\\n bytes callData;\\n }\\n\\n constructor(\\n address _exec,\\n address _euler,\\n address _token,\\n address _dToken\\n ) {\\n exec = _exec;\\n euler = _euler;\\n token = _token;\\n dToken = _dToken;\\n }\\n\\n function _flashCallback(\\n address _initiator,\\n address _asset,\\n uint256 _amount,\\n uint8 _callSource,\\n bytes memory _calldata\\n ) internal virtual {}\\n\\n function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n // sanity checks\\n require(msg.sender == euler);\\n\\n FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n }\\n\\n /**\\n */\\n function _flashLoan(\\n address _asset,\\n uint256 _amount,\\n uint8 _callSource,\\n bytes memory _data\\n ) internal {\\n // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n IExec(exec).deferLiquidityCheck(\\n address(this),\\n abi.encode(\\n FlashloanCallbackData({\\n caller: msg.sender,\\n assetToBorrow: _asset,\\n amountToBorrow: _amount,\\n callSource: _callSource,\\n callData: _data\\n })\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x6a7f3fef2c2eca5a4851e75c632eff2e7c28b4b244ad9fb0bbe2247efe1b395c\",\"license\":\"agpl-3.0\"},\"contracts/periphery/UniswapControllerHelper.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n using Path for bytes;\\n using SafeCast for uint256;\\n using LowGasSafeMath for uint256;\\n using LowGasSafeMath for int256;\\n\\n /// @dev Uniswap factory address\\n address public immutable factory;\\n\\n struct SwapCallbackData {\\n bytes path;\\n address caller;\\n uint8 callSource;\\n bytes callData;\\n }\\n\\n /**\\n * @dev constructor\\n * @param _factory uniswap factory address\\n */\\n constructor(address _factory) {\\n require(_factory != address(0));\\n factory = _factory;\\n }\\n\\n /**\\n * @notice uniswap swap callback function for flashswap\\n * @param amount0Delta amount of token0\\n * @param amount1Delta amount of token1\\n * @param _data callback data encoded as SwapCallbackData struct\\n */\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata _data\\n ) external override {\\n require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n //ensure that callback comes from uniswap pool\\n address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n //determine the amount that needs to be repaid as part of the flashswap\\n uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n }\\n\\n /**\\n * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n * @param _tokenIn token address to sell\\n * @param _tokenOut token address to receive\\n * @param _fee pool fee\\n * @param _amountIn amount to sell\\n * @param _amountOutMinimum minimum amount to receive\\n * @param _callSource function call source\\n * @param _data arbitrary data assigned with the call\\n */\\n function _exactInFlashSwap(\\n address _tokenIn,\\n address _tokenOut,\\n uint24 _fee,\\n uint256 _amountIn,\\n uint256 _amountOutMinimum,\\n uint8 _callSource,\\n bytes memory _data\\n ) internal returns (uint256) {\\n //calls internal uniswap swap function that will trigger a callback for the flash swap\\n uint256 amountOut = _exactInputInternal(\\n _amountIn,\\n address(this),\\n uint160(0),\\n SwapCallbackData({\\n path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n caller: msg.sender,\\n callSource: _callSource,\\n callData: _data\\n })\\n );\\n\\n //slippage limit check\\n require(amountOut >= _amountOutMinimum);\\n\\n return amountOut;\\n }\\n\\n /**\\n * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n * @param _tokenIn token address to sell\\n * @param _tokenOut token address to receive\\n * @param _fee pool fee\\n * @param _amountOut exact amount to receive\\n * @param _amountInMaximum maximum amount to sell\\n * @param _callSource function call source\\n * @param _data arbitrary data assigned with the call\\n */\\n function _exactOutFlashSwap(\\n address _tokenIn,\\n address _tokenOut,\\n uint24 _fee,\\n uint256 _amountOut,\\n uint256 _amountInMaximum,\\n uint8 _callSource,\\n bytes memory _data\\n ) internal {\\n //calls internal uniswap swap function that will trigger a callback for the flash swap\\n uint256 amountIn = _exactOutputInternal(\\n _amountOut,\\n address(this),\\n uint160(0),\\n SwapCallbackData({\\n path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n caller: msg.sender,\\n callSource: _callSource,\\n callData: _data\\n })\\n );\\n\\n //slippage limit check\\n require(amountIn <= _amountInMaximum);\\n }\\n\\n /**\\n * @notice function to be called by uniswap callback.\\n * @dev this function should be overridden by the child contract\\n * param _caller initial strategy function caller\\n * param _tokenIn token address sold\\n * param _tokenOut token address bought\\n * param _fee pool fee\\n * param _amountToPay amount to pay for the pool second token\\n * param _callData arbitrary data assigned with the flashswap call\\n * param _callSource function call source\\n */\\n function _swapCallback(\\n address _caller,\\n address _tokenIn,\\n address _pool,\\n uint256 _amountToPay,\\n bytes memory _callData,\\n uint8 _callSource\\n ) internal virtual {}\\n\\n /**\\n * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n * @param _amountIn amount of token to pay\\n * @param _recipient recipient for receive\\n * @param _sqrtPriceLimitX96 price limit\\n * @return amount of token bought (amountOut)\\n */\\n function _exactInputInternal(\\n uint256 _amountIn,\\n address _recipient,\\n uint160 _sqrtPriceLimitX96,\\n SwapCallbackData memory data\\n ) private returns (uint256) {\\n (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n //uniswap token0 has a lower address than token1\\n //if tokenIn0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n uint256 amount0Min; // minimum amount of token0 to LP\\n uint256 amount1Min; // minimum amount of token1 to LP\\n int24 lowerTick; // range lower tick to LP in\\n int24 upperTick; // range upper tick to LP in\\n }\\n\\n /// @dev params for flashloanCloseVaultLpNft()\\n struct FlashloanCloseVaultLpNftParam {\\n uint256 vaultId; // vault ID\\n uint256 tokenId; // Uni NFT token ID\\n uint256 liquidity; // amount of liquidity in LP position\\n uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n uint256 collateralToWithdraw; // amount of ETH to withdraw\\n uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n uint24 poolFee; // uniswap pool fee\\n bool burnExactRemoved; // flag to set burning exact amount removed from LP or the current contract balance\\n }\\n\\n /// @dev params for _closeUniLp() \\n struct CloseUniLpParams {\\n uint256 tokenId; // Uni v3 NFT id\\n uint256 liquidity; // LP liquidity amount\\n uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n }\\n\\n /// @dev params for sellAll()\\n struct ReduceLiquidityAndSellParams {\\n uint256 tokenId; // Uni token ID\\n uint256 liquidity; // LP liquidity amount\\n uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n }\\n\\n /// @dev params for rebalanceLpWithoutVault()\\n struct RebalanceLpWithoutVaultParams {\\n address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n uint256 tokenId; // Uni token ID\\n uint256 liquidity; // LP liquidity amount\\n uint256 wPowerPerpAmountDesired; // wPowerPerp amount to LP\\n uint256 wethAmountDesired; // WETH amount to LP\\n uint256 amount0DesiredMin; // amount min to get when LPing for asset0\\n uint256 amount1DesiredMin; // amount min to get when LPing for asset1\\n uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n uint256 amount0Min; // amount min to get when closing LP for asset0\\n uint256 amount1Min; // amount min to get when closing LP for asset1\\n int24 lowerTick; // LP lower tick\\n int24 upperTick; // LP upper tick\\n uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n }\\n\\n /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n struct LpWPowerPerpPoolParams {\\n address recipient; // recipient address\\n uint256 amount0Desired; // amount desired to LP for asset0\\n uint256 amount1Desired; // amount desired to LP for asset1\\n uint256 amount0Min; // amount min to LP for asset0\\n uint256 amount1Min; // amount min to LP for asset1\\n int24 lowerTick; // LP lower tick\\n int24 upperTick; // LP upper tick\\n }\\n\\n /// @dev params for rebalanceLpInVault()\\n struct RebalanceLpInVaultParams {\\n RebalanceVaultNftType rebalanceLpInVaultType;\\n bytes data;\\n }\\n\\n /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n struct IncreaseLpLiquidityParams {\\n address wPowerPerpPool; // Uni v3 pool address to increase liquidity in\\n uint256 tokenId; // Uni v3 NFT token id\\n uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n uint256 collateralToDeposit; // collateral to deposit into vault\\n uint256 wethAmountToLp; // WETH amount to LP\\n uint256 amount0Min; // amount min to get for LPing of asset0\\n uint256 amount1Min; // amount min to get for LPing of asset1\\n }\\n\\n /// @dev struct for decrease liquidity in LP position\\n struct DecreaseLpLiquidityParams { \\n uint256 tokenId; // Uni v3 NFT token id\\n uint256 liquidity; // LP liquidity amount\\n uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n uint128 amount0Min; // amount min to get for LPing of asset0\\n uint128 amount1Min; // amount min to get for LPing of asset1\\n }\\n\\n /// @dev struct for minting into vault\\n struct DepositIntoVaultParams {\\n uint256 wPowerPerpToMint; // wPowerPerp amount to mint\\n uint256 collateralToDeposit; // collateral amount to deposit\\n }\\n\\n /// @dev struct for withdrawing from vault\\n struct withdrawFromVaultParams { \\n uint256 wPowerPerpToBurn; // wPowerPerp amount to burn\\n uint256 collateralToWithdraw; // collateral to withdraw\\n bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n }\\n\\n /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n struct GeneralSwapParams {\\n address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n uint256 amountIn; // amount to swap in\\n uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n }\\n\\n /// @dev struct for collecting fees owed from a uniswap NFT\\n struct CollectFeesParams {\\n uint256 tokenId;\\n uint128 amount0Max;\\n uint128 amount1Max;\\n }\\n\\n /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n struct DepositExistingNftParams {\\n uint256 tokenId; // Uni v3 NFT id\\n }\\n}\",\"keccak256\":\"0x04a47d47c3e0a1ec4e834f9aa466960200084fbdee47f0f513990b2c4708b02a\",\"license\":\"BUSL-1.1\"},\"contracts/periphery/lib/ControllerHelperUtil.sol\":{\"content\":\"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n using SafeMath for uint256;\\n using Address for address payable;\\n\\n /**\\n * @notice fully or partially close Uni v3 LP\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n * @return withdrawn wPowerPerp and WETH amounts\\n */\\n function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n .DecreaseLiquidityParams({\\n tokenId: _params.tokenId,\\n liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n amount0Min: _params.amount0Min,\\n amount1Min: _params.amount1Min,\\n deadline: block.timestamp\\n });\\n INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n uint256 wethAmount;\\n uint256 _wPowerPerpAmount;\\n (_isWethToken0)\\n ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n INonfungiblePositionManager.CollectParams({\\n tokenId: _params.tokenId,\\n recipient: address(this),\\n amount0Max: type(uint128).max,\\n amount1Max: type(uint128).max\\n })\\n )\\n : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n INonfungiblePositionManager.CollectParams({\\n tokenId: _params.tokenId,\\n recipient: address(this),\\n amount0Max: type(uint128).max,\\n amount1Max: type(uint128).max\\n })\\n );\\n\\n return (_wPowerPerpAmount, wethAmount);\\n }\\n\\n /**\\n * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n * @param _collateralToLp amount of ETH collateral to LP\\n * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n * @param _lowerTick LP position lower tick\\n * @param _upperTick LP position upper tick\\n * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n * @return exact amount0 and amount1 to be LPed\\n */\\n function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n uint256 amount0Desired; \\n uint256 amount1Desired;\\n\\n {\\n (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n }\\n \\n return (amount0Desired, amount1Desired);\\n }\\n\\n /**\\n * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n * @param _controller wPowerPerp controller address\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n * @return _vaultId and tokenId\\n */\\n function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n \\n uint256 _vaultId = _mintAndLpParams.vaultId;\\n uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n _mintAndLpParams.vaultId,\\n amountToMint,\\n 0\\n );\\n }\\n // LP amount0Desired and amount1Desired in Uni v3\\n uint256 uniTokenId = lpWPowerPerpPool(\\n _nonfungiblePositionManager,\\n _mintAndLpParams.wPowerPerpPool,\\n ControllerHelperDataType.LpWPowerPerpPoolParams({\\n recipient: _mintAndLpParams.recipient,\\n amount0Desired: amount0Desired,\\n amount1Desired: amount1Desired,\\n amount0Min: _mintAndLpParams.amount0Min,\\n amount1Min: _mintAndLpParams.amount1Min,\\n lowerTick: _mintAndLpParams.lowerTick,\\n upperTick: _mintAndLpParams.upperTick\\n })\\n );\\n return (_vaultId, uniTokenId);\\n }\\n\\n /**\\n * @notice increase liquidityin Uni v3 position\\n * @param _controller controller address\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _vaultId vault Id\\n * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n */\\n function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n (\\n ,\\n ,\\n ,\\n ,\\n ,\\n int24 tickLower,\\n int24 tickUpper,\\n ,\\n ,\\n ,\\n ,\\n \\n ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n _vaultId,\\n _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n 0\\n );\\n }\\n }\\n\\n INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n tokenId: _increaseLiquidityParam.tokenId,\\n amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n amount0Min: _increaseLiquidityParam.amount0Min,\\n amount1Min: _increaseLiquidityParam.amount1Min,\\n deadline: block.timestamp\\n });\\n\\n INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n }\\n\\n /**\\n * @notice mint wPowerPerp in vault\\n * @param _controller controller address\\n * @param _weth WETH address\\n * @param _vaultId vault Id\\n * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n * @param _collateralToDeposit amount of collateral to deposit\\n */\\n function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n uint256 vaultId = _vaultId;\\n if (_wPowerPerpToMint > 0) {\\n vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n _vaultId,\\n _wPowerPerpToMint,\\n 0\\n );\\n } else {\\n IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n }\\n return vaultId;\\n }\\n\\n /**\\n * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n * @param _controller controller address\\n * @param _weth weth address\\n * @param _vaultId vault Id\\n * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n * @param _collateralToWithdraw amount of collateral to withdraw\\n */\\n function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n IController(_controller).burnWPowerPerpAmount(\\n _vaultId,\\n _wPowerPerpToBurn,\\n _collateralToWithdraw\\n );\\n\\n if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n }\\n\\n /**\\n * @notice LP into Uniswap V3 pool\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n */\\n function lpWPowerPerpPool(\\n address _nonfungiblePositionManager,\\n address _wPowerPerpPool,\\n ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n ) public returns (uint256) {\\n INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n tickLower: int24(_params.lowerTick),\\n tickUpper: int24(_params.upperTick),\\n amount0Desired: _params.amount0Desired,\\n amount1Desired: _params.amount1Desired,\\n amount0Min: _params.amount0Min,\\n amount1Min: _params.amount1Min,\\n recipient: _params.recipient,\\n deadline: block.timestamp\\n });\\n (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n mintParams\\n );\\n return tokenId;\\n }\\n\\n /**\\n * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n * @param _user user address\\n * @param _controller controller address\\n * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n * @param _vaultId vault ID\\n * @param _tokenId Uni LP NFT id\\n * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n */\\n function checkClosedLp(\\n address _user,\\n address _controller,\\n address _nonfungiblePositionManager,\\n uint256 _vaultId,\\n uint256 _tokenId,\\n uint256 _liquidityPercentage\\n ) public {\\n if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n address(this),\\n _user,\\n _tokenId\\n );\\n } else {\\n IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n }\\n }\\n\\n /**\\n * @notice send ETH and wPowerPerp\\n * @param _weth WETH address\\n * @param _wPowerPerp wPowerPerp address\\n */\\n function sendBack(address _weth, address _wPowerPerp) public {\\n IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n payable(msg.sender).sendValue(address(this).balance);\\n uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n if (wPowerPerpBalance > 0) {\\n IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n }\\n }\\n}\",\"keccak256\":\"0x51c6185083d747a36ee8543219c0e7a326b866c0bdc113e82956cd4e226f7ba3\",\"license\":\"BUSL-1.1\"},\"contracts/periphery/lib/LiquidityAmounts.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n /// @notice Downcasts uint256 to uint128\\n /// @param x The uint258 to be downcasted\\n /// @return y The passed value, downcasted to uint128\\n function toUint128(uint256 x) private pure returns (uint128 y) {\\n require((y = uint128(x)) == x);\\n }\\n\\n /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param amount0 The amount0 being sent in\\n /// @return liquidity The amount of returned liquidity\\n function getLiquidityForAmount0(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint256 amount0\\n ) internal pure returns (uint128 liquidity) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n }\\n\\n /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param amount1 The amount1 being sent in\\n /// @return liquidity The amount of returned liquidity\\n function getLiquidityForAmount1(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint256 amount1\\n ) internal pure returns (uint128 liquidity) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n }\\n\\n /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n /// pool prices and the prices at the tick boundaries\\n /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param amount0 The amount of token0 being sent in\\n /// @param amount1 The amount of token1 being sent in\\n /// @return liquidity The maximum amount of liquidity received\\n function getLiquidityForAmounts(\\n uint160 sqrtRatioX96,\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint256 amount0,\\n uint256 amount1\\n ) internal pure returns (uint128 liquidity) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n if (sqrtRatioX96 <= sqrtRatioAX96) {\\n liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n } else {\\n liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n }\\n }\\n\\n /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param liquidity The liquidity being valued\\n /// @return amount0 The amount of token0\\n function getAmount0ForLiquidity(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity\\n ) internal pure returns (uint256 amount0) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n return\\n FullMath.mulDiv(\\n uint256(liquidity) << FixedPoint96.RESOLUTION,\\n sqrtRatioBX96 - sqrtRatioAX96,\\n sqrtRatioBX96\\n ) / sqrtRatioAX96;\\n }\\n\\n /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param liquidity The liquidity being valued\\n /// @return amount1 The amount of token1\\n function getAmount1ForLiquidity(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity\\n ) internal pure returns (uint256 amount1) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n }\\n\\n /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n /// pool prices and the prices at the tick boundaries\\n /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n /// @param liquidity The liquidity being valued\\n /// @return amount0 The amount of token0\\n /// @return amount1 The amount of token1\\n function getAmountsForLiquidity(\\n uint160 sqrtRatioX96,\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n uint128 liquidity\\n ) internal pure returns (uint256 amount0, uint256 amount1) {\\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n if (sqrtRatioX96 <= sqrtRatioAX96) {\\n amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n } else {\\n amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n }\\n }\\n\\n function getAmountsFromLiquidity( \\n uint160 sqrtRatioX96,\\n int24 currentTick,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity\\n ) internal pure returns (uint256 amount0, uint256 amount1) {\\n if (currentTick < tickLower) {\\n amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n TickMath.getSqrtRatioAtTick(tickLower),\\n TickMath.getSqrtRatioAtTick(tickUpper),\\n liquidity,\\n false\\n );\\n } else if (currentTick < tickUpper) {\\n amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n sqrtRatioX96,\\n TickMath.getSqrtRatioAtTick(tickUpper),\\n liquidity,\\n false\\n );\\n amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n TickMath.getSqrtRatioAtTick(tickLower),\\n sqrtRatioX96,\\n liquidity,\\n false\\n );\\n } else {\\n amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n TickMath.getSqrtRatioAtTick(tickLower),\\n TickMath.getSqrtRatioAtTick(tickUpper),\\n liquidity,\\n false\\n );\\n }\\n \\n }\\n\\n}\\n\",\"keccak256\":\"0xb4b0f464529a43f3ca7a9d6afc5976902c0a004649bdf3239ca77469d26b7cf2\",\"license\":\"GPL-2.0-or-later\"}},\"version\":1}", - "bytecode": "0x6101e06040523480156200001257600080fd5b5060405162006a3e38038062006a3e833981016040819052620000359162000679565b8282876001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200007157600080fd5b505afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac919062000655565b83876001600160a01b038116620000c257600080fd5b6001600160601b0319606091821b811660805294811b851660a05292831b841660c05290821b831660e052811b82166101005287901b166101405260408051634ea64a2160e11b815290516001600160a01b03881691639d4c9442916004808301926020929190829003018186803b1580156200013e57600080fd5b505afa15801562000153573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000179919062000655565b6001600160a01b0316610160816001600160a01b031660601b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b158015620001d057600080fd5b505afa158015620001e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020b919062000655565b6001600160a01b0316610180816001600160a01b031660601b81525050856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200026257600080fd5b505afa15801562000277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029d919062000655565b6001600160601b0319606091821b81166101a0529086901b166101c052604080516307f07b1360e41b815290516001600160a01b03881691637f07b130916004808301926020929190829003018186803b158015620002fb57600080fd5b505afa15801562000310573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000336919062000655565b6001600160a01b0316866001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200037957600080fd5b505afa1580156200038e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003b4919062000655565b6001600160a01b031610151561012081151560f81b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200040757600080fd5b505afa1580156200041c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000442919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200047392919062000736565b602060405180830381600087803b1580156200048e57600080fd5b505af1158015620004a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c99190620006f9565b50856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200050457600080fd5b505afa15801562000519573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200053f919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200057092919062000736565b602060405180830381600087803b1580156200058b57600080fd5b505af1158015620005a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c69190620006f9565b5060405163a22cb46560e01b81526001600160a01b0386169063a22cb46590620005f89089906001906004016200071b565b600060405180830381600087803b1580156200061357600080fd5b505af115801562000628573d6000803e3d6000fd5b505050505050505050506200074f565b80516001600160a01b03811681146200065057600080fd5b919050565b60006020828403121562000667578081fd5b620006728262000638565b9392505050565b60008060008060008060c0878903121562000692578182fd5b6200069d8762000638565b9550620006ad6020880162000638565b9450620006bd6040880162000638565b9350620006cd6060880162000638565b9250620006dd6080880162000638565b9150620006ed60a0880162000638565b90509295509295509295565b6000602082840312156200070b578081fd5b8151801515811462000672578182fd5b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160f81c6101405160601c6101605160601c6101805160601c6101a05160601c6101c05160601c615fe162000a5d600039806102f452806103dc52806104cd52806108aa5280610b315280610cca5280610efc5280610f8652806110f1528061183f52806118d55280611a4152806120bc52806125eb528061274a5280612a5f5280612bff5280612d5552806132cb528061367e52508061074952806108275280610a385280610acf5280610bef5280610d0e5280610e67528061118252806111fc528061125e52806112c4528061136652806113d3528061177a5280611c0552806120fe52806122f5528061246852806128405280612e0b5280612f13528061310852806131d0528061330d528061349b528061355b528061384d528061392552806139a45280613a6a5280613b0b5280613c405280613cad5280613df5528061404e528061411d52508061076a52806108065280610a5a5280610c115280610cec5280610e895280611161528061121e52806112e652806113f452806116ae528061175952806120dd5280612a815280612ff352806132ec52806134db528061351b52806139c55280613aea5280613f165280613f86525080610dcc5280611e7252806123a25280613e915250806104ab5280610ca852806110cf5280611a1f528061209b528061224f52806122d452806124e65280612565528061272852806128bc528061293b5280612a3d5280612b145280612d335280612ef152806130e652806131ae52806132aa52806133da5280613789528061382b52806139035280613a485280613c1e5280613dd352806140fb52806144985250806103ff528061053d52806105b852806106a852806108f252806109245280610d32528061100d528061195e52806121a4528061265b5280612aa85280612c6d528061332f5250806114b052806116195280611aea525080611bdb52508061146c52806115695280611b0e5250806117d85280611f145250806117fc5280611b7752806147505250615fe16000f3fe6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b81526000935073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b815290915073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f0000000000000000000000000000000000000000000000000000000000000000156106515773B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b73B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b73B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b815260009073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b50505050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b815291925073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b815290915073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b905060008073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b5050505073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b50505050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b815291925073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b905073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b9050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b815260009373B53c2eE92A24B08521912e1687Bc8142a7E6a9EE93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033", - "deployedBytecode": "0x6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b81526000935073__$561e80098325da493156966792c25e3551$__925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f0000000000000000000000000000000000000000000000000000000000000000156106515773__$561e80098325da493156966792c25e3551$__63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b73__$561e80098325da493156966792c25e3551$__63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b73__$561e80098325da493156966792c25e3551$__63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b815260009073__$561e80098325da493156966792c25e3551$__90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b815291925073__$561e80098325da493156966792c25e3551$__9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b905060008073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b5050505073__$561e80098325da493156966792c25e3551$__6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b815293945073__$561e80098325da493156966792c25e3551$__9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b815291925073__$561e80098325da493156966792c25e3551$__91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b905073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b815273__$561e80098325da493156966792c25e3551$__9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b815273__$561e80098325da493156966792c25e3551$__92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b9050600073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b815260009373__$561e80098325da493156966792c25e3551$__93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033", - "libraries": { - "ControllerHelperUtil": "0xB53c2eE92A24B08521912e1687Bc8142a7E6a9EE" + { + "inputs": [], + "name": "dToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" }, - "devdoc": { - "kind": "dev", - "methods": { - "closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))": { - "details": "user should approve this contract for Uni NFT transfer", - "params": { - "_params": "ControllerHelperDataType.CloseShortWithUserNftParams struct" - } - }, - "flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))": { - "details": "sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan", - "params": { - "_params": "ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct" - } - }, - "flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))": { - "details": "flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp", - "params": { - "_params": "ControllerHelperDataType.FlashSellLongWMintParams struct" - } - }, - "flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))": { - "details": "this function", - "params": { - "_params": "ControllerHelperDataType.FlashswapWBurnBuyLongParams struct" - } - }, - "onERC721Received(address,address,uint256,bytes)": { - "details": "accept erc721 from safeTransferFrom and safeMint after callback", - "returns": { - "_0": "returns received selector" - } - }, - "rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])": { - "params": { - "_collateralToFlashloan": "collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT", - "_params": "array of ControllerHelperDataType.RebalanceLpInVaultParams structs", - "_vaultId": "vault ID" - } - }, - "rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))": { - "params": { - "_params": "ControllerHelperDataType.RebalanceLpWithoutVaultParams struct" - } - }, - "reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))": { - "params": { - "_params": "ControllerHelperDataType.ReduceLiquidityAndSellParams struct" - } - }, - "uniswapV3SwapCallback(int256,int256,bytes)": { - "params": { - "_data": "callback data encoded as SwapCallbackData struct", - "amount0Delta": "amount of token0", - "amount1Delta": "amount of token1" - } - }, - "wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))": { - "params": { - "_params": "ControllerHelperDataType.MintAndLpParams struct" - } + { + "inputs": [], + "name": "euler", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" } - }, - "version": 1 + ], + "stateMutability": "view", + "type": "function" }, - "userdoc": { - "kind": "user", - "methods": { - "closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))": { - "notice": "close short position with user Uniswap v3 LP NFT" - }, - "flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))": { - "notice": "FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan" + { + "inputs": [], + "name": "exec", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidityPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToFlashloan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToWithdraw", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limitPriceEthPerPowerPerp", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0Min", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Min", + "type": "uint128" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + }, + { + "internalType": "bool", + "name": "burnExactRemoved", + "type": "bool" + } + ], + "internalType": "struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam", + "name": "_params", + "type": "tuple" + } + ], + "name": "flashloanCloseVaultLpNft", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "wPowerPerpPool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToFlashloan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToLp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToWithdraw", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "lowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "upperTick", + "type": "int24" + } + ], + "internalType": "struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "flashloanWMintLpDepositNft", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToMint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToSell", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minToReceive", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + } + ], + "internalType": "struct ControllerHelperDataType.FlashSellLongWMintParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "flashswapSellLongWMint", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountToBuy", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToWithdraw", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxToPay", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + } + ], + "internalType": "struct ControllerHelperDataType.FlashswapWBurnBuyLongParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "flashswapWBurnBuyLong", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedData", + "type": "bytes" + } + ], + "name": "onDeferredLiquidityCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" }, - "flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))": { - "notice": "sell long wPowerPerp and flashswap mint short position" + { + "internalType": "address", + "name": "", + "type": "address" }, - "flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))": { - "notice": "flash close position and buy long squeeth" + { + "internalType": "uint256", + "name": "", + "type": "uint256" }, - "rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])": { - "notice": "Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault" + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_vaultId", + "type": "uint256" }, - "rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))": { - "notice": "Rebalance LP nft through trading" + { + "internalType": "uint256", + "name": "_collateralToFlashloan", + "type": "uint256" }, - "reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))": { - "notice": "sell all LP wPowerPerp amounts to WETH and send back to user" + { + "components": [ + { + "internalType": "enum ControllerHelperDataType.RebalanceVaultNftType", + "name": "rebalanceLpInVaultType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct ControllerHelperDataType.RebalanceLpInVaultParams[]", + "name": "_params", + "type": "tuple[]" + } + ], + "name": "rebalanceLpInVault", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "wPowerPerpPool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmountDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wethAmountDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0DesiredMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1DesiredMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limitPriceEthPerPowerPerp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "lowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "upperTick", + "type": "int24" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + } + ], + "internalType": "struct ControllerHelperDataType.RebalanceLpWithoutVaultParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "rebalanceLpWithoutVault", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidityPercentage", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0Min", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Min", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "limitPriceEthPerPowerPerp", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "poolFee", + "type": "uint24" + } + ], + "internalType": "struct ControllerHelperDataType.ReduceLiquidityAndSellParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "reduceLiquidityAndSell", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" }, - "uniswapV3SwapCallback(int256,int256,bytes)": { - "notice": "uniswap swap callback function for flashswap" + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" }, - "wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))": { - "notice": "mint WPowerPerp and LP into Uniswap v3 pool" + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" } - }, - "version": 1 + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "wPowerPerpPool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vaultId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "wPowerPerpAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateralToLp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "lowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "upperTick", + "type": "int24" + } + ], + "internalType": "struct ControllerHelperDataType.MintAndLpParams", + "name": "_params", + "type": "tuple" + } + ], + "name": "wMintLp", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, - "storageLayout": { - "storage": [], - "types": null + { + "stateMutability": "payable", + "type": "receive" } -} \ No newline at end of file +] \ No newline at end of file From 671a40e9ac424968072e77ebd291407ada045296 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 16 Jun 2022 20:00:36 -0700 Subject: [PATCH 11/82] tx goes through, decimal refinement needed --- packages/frontend/src/state/lp/hooks.ts | 51 ++++++++++--------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 17c28a202..948ae7272 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -4,7 +4,7 @@ import { fromTokenAmount } from '@utils/calculations' import { useAtom, useAtomValue } from 'jotai' import { addressesAtom, isWethToken0Atom } from '../positions/atoms' import BigNumber from 'bignumber.js' -import { BIG_ZERO, OSQUEETH_DECIMALS } from '@constants/index' +import { BIG_ZERO, INDEX_SCALE, OSQUEETH_DECIMALS } from '@constants/index' import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom } from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' import { addressAtom } from '../wallet/atoms' @@ -133,7 +133,6 @@ export const useOpenPosition = () => { // Opening a mint and LP position and depositing export const useOpenPositionDeposit = () => { const { squeethPool } = useAtomValue(addressesAtom) - const normalizationFactor = useAtomValue(normFactorAtom) const address = useAtomValue(addressAtom) const contract = useAtomValue(controllerHelperHelperContractAtom) const handleTransaction = useHandleTransaction() @@ -141,24 +140,21 @@ export const useOpenPositionDeposit = () => { const ethPrice = useAtomValue(wethPriceAtom) const squeethPrice = useAtomValue(squeethPriceeAtom) const openPositionDeposit = useAppCallback( - async ( - ethAmount: BigNumber, - squeethToMint: BigNumber, - lowerTickInput: number, - upperTickInput: number, - onTxConfirmed?: () => void, - ) => { - const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS).multipliedBy(normalizationFactor) - const mintRSqueethAmount = mintWSqueethAmount.multipliedBy(normFactor).div(one) - const scaledEthPrice = ethPrice.div(10000) - const debtInEth = mintRSqueethAmount.multipliedBy(scaledEthPrice).div(one) + async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { + // const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS).multipliedBy(normalizationFactor) + // const mintRSqueethAmount = mintWSqueethAmount.multipliedBy(normFactor).div(one) + // console.log('scaledEthPrice', ethPrice.toString()) + // const debtInEth = mintRSqueethAmount.multipliedBy(ethPrice) + // const ethAmt = fromTokenAmount(ethAmount, 18).toFixed(0) + + const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) + const ethDebt = mintWSqueethAmount.multipliedBy(normFactor).multipliedBy(ethPrice) // Do we want to hardcode a 150% collateralization ratio? - const collateralToMint = debtInEth.multipliedBy(3).div(2).plus(0.01) - const collateralToLp = mintWSqueethAmount.multipliedBy(squeethPrice).div(one) - const flashloanFee = collateralToMint.multipliedBy(9).div(1000) + const collateralToMint = ethDebt.multipliedBy(3).div(2) + const collateralToLp = mintWSqueethAmount.multipliedBy(squeethPrice) - // Closest 60 tick width above or below current tick (60 is minimum tick width for 30bps pool) + const flashloanFee = collateralToMint.multipliedBy(9).div(1000) const lowerTick = nearestUsableTick(lowerTickInput, 3000) const upperTick = nearestUsableTick(upperTickInput, 3000) @@ -166,28 +162,23 @@ export const useOpenPositionDeposit = () => { const flashloanWMintDepositNftParams = { wPowerPerpPool: squeethPool, vaultId: 0, - wPowerPerpAmount: mintWSqueethAmount.toString(), - collateralToDeposit: collateralToMint.toString(), - collateralToFlashloan: collateralToMint.toString(), - collateralToLp: collateralToLp.toString(), + wPowerPerpAmount: mintWSqueethAmount.toFixed(0), + collateralToDeposit: collateralToMint.toFixed(0), + collateralToFlashloan: collateralToMint.toFixed(0), + collateralToLp: collateralToLp.toFixed(0), collateralToWithdraw: 0, amount0Min: 0, amount1Min: 0, lowerTick: lowerTick, upperTick: upperTick, } - if (!contract || !address) return null return handleTransaction( - contract.methods - .flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, { - value: collateralToLp.plus(flashloanFee).plus(0.01).toString(), - }) - .send({ - from: address, - value: fromTokenAmount(ethAmount, 18), - }), + contract.methods.flashloanWMintLpDepositNft(flashloanWMintDepositNftParams).send({ + from: address, + value: collateralToLp.plus(flashloanFee).toFixed(0), + }), onTxConfirmed, ) }, From 6a0fac995789f445ae42ead8fa8c10e46f384426 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Fri, 17 Jun 2022 17:55:41 -0700 Subject: [PATCH 12/82] testing, debugging, using old hooks for open pos deposit --- .../frontend/src/state/controller/hooks.ts | 12 +++++++++++ packages/frontend/src/state/lp/hooks.ts | 20 ++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/frontend/src/state/controller/hooks.ts b/packages/frontend/src/state/controller/hooks.ts index 830e0ff39..d0a3d1bde 100644 --- a/packages/frontend/src/state/controller/hooks.ts +++ b/packages/frontend/src/state/controller/hooks.ts @@ -210,6 +210,18 @@ export const useGetTwapEthPrice = () => { return getTwapEthPrice } +export const useGetTwapSqueethPrice = () => { + const { squeethPool, oSqueeth, weth } = useAtomValue(addressesAtom) + const { getTwapSafe } = useOracle() + console.log(squeethPool, oSqueeth, weth) + const getTwapSqueethPrice = useCallback( + async () => await getTwapSafe(squeethPool, oSqueeth, weth, TWAP_PERIOD), + [oSqueeth, weth, getTwapSafe, squeethPool], + ) + + return getTwapSqueethPrice +} + export const useGetShortAmountFromDebt = () => { const { ethUsdcPool, weth, usdc } = useAtomValue(addressesAtom) const normFactor = useAtomValue(normFactorAtom) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 948ae7272..273b0c226 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -17,6 +17,7 @@ import { useGetSellQuote } from '../squeethPool/hooks' import { useUpdateAtom } from 'jotai/utils' import { lowerTickAtom, upperTickAtom } from './atoms' import { useMemo } from 'react' +import { useGetDebtAmount, useGetTwapEthPrice, useGetTwapSqueethPrice } from '../controller/hooks' /*** CONSTANTS ***/ const one = new BigNumber(10).pow(18) @@ -136,24 +137,17 @@ export const useOpenPositionDeposit = () => { const address = useAtomValue(addressAtom) const contract = useAtomValue(controllerHelperHelperContractAtom) const handleTransaction = useHandleTransaction() - const normFactor = useAtomValue(normFactorAtom) - const ethPrice = useAtomValue(wethPriceAtom) - const squeethPrice = useAtomValue(squeethPriceeAtom) + const getTwapSqueethPrice = useGetTwapSqueethPrice() + const getDebtAmount = useGetDebtAmount() const openPositionDeposit = useAppCallback( async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { - // const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS).multipliedBy(normalizationFactor) - // const mintRSqueethAmount = mintWSqueethAmount.multipliedBy(normFactor).div(one) - // console.log('scaledEthPrice', ethPrice.toString()) - // const debtInEth = mintRSqueethAmount.multipliedBy(ethPrice) - // const ethAmt = fromTokenAmount(ethAmount, 18).toFixed(0) - + const squeethPrice = await getTwapSqueethPrice() + console.log('squeeth price', squeethPrice.toString()) const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) - const ethDebt = mintWSqueethAmount.multipliedBy(normFactor).multipliedBy(ethPrice) - + const ethDebt = await getDebtAmount(mintWSqueethAmount) // Do we want to hardcode a 150% collateralization ratio? const collateralToMint = ethDebt.multipliedBy(3).div(2) const collateralToLp = mintWSqueethAmount.multipliedBy(squeethPrice) - const flashloanFee = collateralToMint.multipliedBy(9).div(1000) const lowerTick = nearestUsableTick(lowerTickInput, 3000) @@ -172,6 +166,8 @@ export const useOpenPositionDeposit = () => { lowerTick: lowerTick, upperTick: upperTick, } + + console.log('flashloanWMintDepositNftParams from hooks', flashloanWMintDepositNftParams) if (!contract || !address) return null return handleTransaction( From 18dc6e63ac1421be296d8a33aa54cd01d2d6d9ea Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Fri, 17 Jun 2022 21:51:52 -0700 Subject: [PATCH 13/82] log --- packages/frontend/src/state/controller/hooks.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/frontend/src/state/controller/hooks.ts b/packages/frontend/src/state/controller/hooks.ts index d0a3d1bde..5217b2751 100644 --- a/packages/frontend/src/state/controller/hooks.ts +++ b/packages/frontend/src/state/controller/hooks.ts @@ -213,7 +213,6 @@ export const useGetTwapEthPrice = () => { export const useGetTwapSqueethPrice = () => { const { squeethPool, oSqueeth, weth } = useAtomValue(addressesAtom) const { getTwapSafe } = useOracle() - console.log(squeethPool, oSqueeth, weth) const getTwapSqueethPrice = useCallback( async () => await getTwapSafe(squeethPool, oSqueeth, weth, TWAP_PERIOD), [oSqueeth, weth, getTwapSafe, squeethPool], From 8a214c6990a033b3490b8715e5d99a922446705e Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Fri, 17 Jun 2022 23:15:02 -0700 Subject: [PATCH 14/82] fixing close position --- packages/frontend/src/state/lp/hooks.ts | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 273b0c226..3fc7b2e04 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -34,31 +34,38 @@ export const useClosePosition = () => { const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) const { controllerHelper } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) - const handleTransaction = useHandleTransaction() - const squeethPrice = useAtomValue(squeethPriceeAtom) - const ethPrice = useAtomValue(wethPriceAtom) const positionManager = useAtomValue(nftManagerContractAtom) + const handleTransaction = useHandleTransaction() + const getTwapSqueethPrice = useGetTwapSqueethPrice() + const getDebtAmount = useGetDebtAmount() const closePosition = useAppCallback(async (vaultId: BigNumber, onTxConfirmed?: () => void) => { - if (!controllerContract || !controllerHelperContract || !address || !positionManager) return - const one = new BigNumber(10).pow(18) const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId const vaultBefore = await controllerContract?.methods.vaults(vaultId) - const scaledEthPrice = ethPrice.div(10000) - const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one) - const collateralToFlashloan = debtInEth.mul(3).div(2).add(0.01) + if ( + !controllerContract || + !controllerHelperContract || + !address || + !positionManager || + !vaultBefore || + !vaultBefore.shortAmount + ) + return + const debtInEth = await getDebtAmount(vaultBefore.shortAmount) + const collateralToFlashloan = debtInEth.multipliedBy(1.5) + // What should we set as slippage const slippage = new BigNumber(3).multipliedBy(new BigNumber(10).pow(16)) + const squeethPrice = await getTwapSqueethPrice() const limitPriceEthPerPowerPerp = squeethPrice.multipliedBy(one.minus(slippage)).div(one) const positionBefore = await positionManager.methods.positions(uniTokenId) - const flashloanCloseVaultLpNftParam = { vaultId: vaultId, tokenId: uniTokenId, liquidity: positionBefore.liquidity, - liquidityPercentage: 1, - wPowerPerpAmountToBurn: vaultBefore.shortAmount.toString(), - collateralToFlashloan: collateralToFlashloan.toString(), + liquidityPercentage: fromTokenAmount(1, 18).toFixed(0), + wPowerPerpAmountToBurn: vaultBefore.shortAmount.toFixed(0), + collateralToFlashloan: collateralToFlashloan.toFixed(0), collateralToWithdraw: 0, - limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp.toString(), + limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp.toFixed(0), amount0Min: 0, amount1Min: 0, poolFee: 3000, From 5b8e7e7738f4f9c3da815e63e3479e46582402bc Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Fri, 17 Jun 2022 23:17:02 -0700 Subject: [PATCH 15/82] removing mint and LP function --- packages/frontend/src/state/lp/hooks.ts | 54 ------------------------- 1 file changed, 54 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 3fc7b2e04..3b88b9071 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -84,60 +84,6 @@ export const useClosePosition = () => { return closePosition } -// Opening a mint and LP position -export const useOpenPosition = () => { - const { squeethPool } = useAtomValue(addressesAtom) - const normalizationFactor = useAtomValue(normFactorAtom) - const address = useAtomValue(addressAtom) - const contract = useAtomValue(controllerHelperHelperContractAtom) - const handleTransaction = useHandleTransaction() - const openPosition = useAppCallback( - async ( - ethAmount: BigNumber, - squeethToMint: BigNumber, - collateralAmount: BigNumber, - vaultId: BigNumber, - lowerTickInput: number, - upperTickInput: number, - onTxConfirmed?: () => void, - ) => { - const amount0Min = BIG_ZERO - const amount1Min = BIG_ZERO - const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS).multipliedBy(normalizationFactor) - - // Closest 60 tick width above or below current tick (60 is minimum tick width for 30bps pool) - - const lowerTick = nearestUsableTick(lowerTickInput, 3000) - const upperTick = nearestUsableTick(upperTickInput, 3000) - - const params = { - recipient: address, - wPowerPerpPool: squeethPool, - vaultId: vaultId, - wPowerPerpAmount: mintWSqueethAmount, - collateralToDeposit: collateralAmount, - collateralToLp: BIG_ZERO, - amount0Min: amount0Min, - amount1Min: amount1Min, - lowerTick: lowerTick, - upperTick: upperTick, - } - - if (!contract || !address) return null - - return handleTransaction( - contract.methods.wMintLp(params, { value: collateralAmount }).send({ - from: address, - value: fromTokenAmount(ethAmount, 18), - }), - onTxConfirmed, - ) - }, - [], - ) - return openPosition -} - // Opening a mint and LP position and depositing export const useOpenPositionDeposit = () => { const { squeethPool } = useAtomValue(addressesAtom) From 7d32b3133b2fa26f213a931cc25ef7a72ec6b109 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Fri, 17 Jun 2022 23:45:18 -0700 Subject: [PATCH 16/82] taking out safety margin --- packages/frontend/src/state/lp/hooks.ts | 65 ++++++++++++------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 3b88b9071..0e5f1090a 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -143,15 +143,22 @@ export const useCollectFees = () => { const { controllerHelper } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() - const ethPrice = useAtomValue(wethPriceAtom) const positionManager = useAtomValue(nftManagerContractAtom) + const getDebtAmount = useGetDebtAmount() const collectFees = useAppCallback(async (vaultId: BigNumber, onTxConfirmed?: () => void) => { - if (!controllerContract || !controllerHelperContract || !address || !positionManager) return const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId const vaultBefore = await controllerContract?.methods.vaults(vaultId) - const scaledEthPrice = ethPrice.div(10000) - const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one) - const collateralToFlashloan = debtInEth.mul(3).div(2).add(0.01) + if ( + !controllerContract || + !controllerHelperContract || + !address || + !positionManager || + !vaultBefore || + !vaultBefore.shortAmount + ) + return + const debtInEth = await getDebtAmount(vaultBefore.shortAmount) + const collateralToFlashloan = debtInEth.multipliedBy(1.5) const amount0Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1) const amount1Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1) @@ -188,28 +195,25 @@ export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: num export const useRebalanceVault = () => { const address = useAtomValue(addressAtom) const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) - const { controllerHelper, weth, oSqueeth, squeethPool } = useAtomValue(addressesAtom) + const { controllerHelper, squeethPool } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() - const ethPrice = useAtomValue(wethPriceAtom) const positionManager = useAtomValue(nftManagerContractAtom) const isWethToken0 = useAtomValue(isWethToken0Atom) const getSellQuote = useGetSellQuote() + const getDebtAmount = useGetDebtAmount() const rebalanceVault = useAppCallback( async (vaultId: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { if (!controllerContract || !controllerHelperContract || !address || !positionManager) return - const one = new BigNumber(10).pow(18) const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId const positionBefore = await positionManager.methods.positions(uniTokenId) const vaultBefore = await controllerContract?.methods.vaults(vaultId) - const scaledEthPrice = ethPrice.div(10000) - const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one) - const collateralToFlashloan = debtInEth.mul(3).div(2).add(0.01) + const debtInEth = await getDebtAmount(vaultBefore.shortAmount) + const collateralToFlashloan = debtInEth.multipliedBy(1.5) const tokenIndex = await positionManager.methods.totalSupply() const tokenId = await positionManager.methods.tokenByIndex(tokenIndex.sub(1)) const amount0Min = new BigNumber(0) const amount1Min = new BigNumber(0) - const safetyWPowerPerp = ethers.utils.parseUnits('0.01') const lowerTick = nearestUsableTick(lowerTickInput, 3000) const upperTick = nearestUsableTick(upperTickInput, 3000) @@ -229,8 +233,7 @@ export const useRebalanceVault = () => { const ethAmountOutFromSwap = getSellQuote(wPowerPerpAmountInLPBefore) // Estimate of new LP with 0.01 weth safety margin - const safetyEth = ethers.utils.parseUnits('0.01') - const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap).sub(safetyEth) + const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap) const abiCoder = new ethers.utils.AbiCoder() const rebalanceLpInVaultParams = [ @@ -243,9 +246,9 @@ export const useRebalanceVault = () => { [ tokenId, positionBefore.liquidity, - new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toString(), - new BigNumber(0).toString(), - new BigNumber(0).toString(), + new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toFixed(0), + new BigNumber(0).toFixed(0), + new BigNumber(0).toFixed(0), ], ), }, @@ -274,8 +277,8 @@ export const useRebalanceVault = () => { controllerHelper, squeethPool, vaultId, - new BigNumber(0).toString(), - new BigNumber(0).toString(), + new BigNumber(0).toFixed(0), + new BigNumber(0).toFixed(0), wethAmountToLP, amount0Min, amount1Min, @@ -308,25 +311,22 @@ export const useRebalanceGeneralSwap = () => { const { controllerHelper, weth, oSqueeth, squeethPool } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() - const ethPrice = useAtomValue(wethPriceAtom) const positionManager = useAtomValue(nftManagerContractAtom) const isWethToken0 = useAtomValue(isWethToken0Atom) const getSellQuote = useGetSellQuote() + const getDebtAmount = useGetDebtAmount() const rebalanceGeneralSwap = useAppCallback( async (vaultId: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { if (!controllerContract || !controllerHelperContract || !address || !positionManager) return - const one = new BigNumber(10).pow(18) const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId const positionBefore = await positionManager.methods.positions(uniTokenId) const vaultBefore = await controllerContract?.methods.vaults(vaultId) - const scaledEthPrice = ethPrice.div(10000) - const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one) - const collateralToFlashloan = debtInEth.mul(3).div(2).add(0.01) + const debtInEth = await getDebtAmount(vaultBefore.shortAmount) + const collateralToFlashloan = debtInEth.multipliedBy(1.5) const tokenIndex = await positionManager.methods.totalSupply() const tokenId = await positionManager.methods.tokenByIndex(tokenIndex.sub(1)) const amount0Min = new BigNumber(0) const amount1Min = new BigNumber(0) - const safetyWPowerPerp = ethers.utils.parseUnits('0.01') const lowerTick = nearestUsableTick(lowerTickInput, 3000) const upperTick = nearestUsableTick(upperTickInput, 3000) @@ -346,8 +346,7 @@ export const useRebalanceGeneralSwap = () => { const ethAmountOutFromSwap = getSellQuote(wPowerPerpAmountInLPBefore) // Estimate of new LP with 0.01 weth safety margin - const safetyEth = ethers.utils.parseUnits('0.01') - const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap).sub(safetyEth) + const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap) const abiCoder = new ethers.utils.AbiCoder() const rebalanceLpInVaultParams = [ @@ -360,9 +359,9 @@ export const useRebalanceGeneralSwap = () => { [ tokenId, positionBefore.liquidity, - new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toString(), - new BigNumber(0).toString(), - new BigNumber(0).toString(), + new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toFixed(0), + new BigNumber(0).toFixed(0), + new BigNumber(0).toFixed(0), ], ), }, @@ -372,7 +371,7 @@ export const useRebalanceGeneralSwap = () => { // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice] data: abiCoder.encode( ['address', 'address', 'uint256', 'uint256', 'uint24'], - [oSqueeth, weth, wPowerPerpAmountInLPBefore.sub(safetyWPowerPerp), new BigNumber(0).toString(), 3000], + [oSqueeth, weth, wPowerPerpAmountInLPBefore, new BigNumber(0).toFixed(0), 3000], ), }, { @@ -385,8 +384,8 @@ export const useRebalanceGeneralSwap = () => { controllerHelper, squeethPool, vaultId, - new BigNumber(0).toString(), - new BigNumber(0).toString(), + new BigNumber(0).toFixed(0), + new BigNumber(0).toFixed(0), wethAmountToLP, amount0Min, amount1Min, From cf5e5d23d85c85accba6993ea993fb756e52856c Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 21 Jun 2022 13:44:51 -0700 Subject: [PATCH 17/82] add ropsten controller helper address --- packages/frontend/src/constants/address.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/constants/address.ts b/packages/frontend/src/constants/address.ts index ce697a25e..6c4e0fd6e 100644 --- a/packages/frontend/src/constants/address.ts +++ b/packages/frontend/src/constants/address.ts @@ -127,7 +127,7 @@ export const ZERO_ADDR = '0x0000000000000000000000000000000000000000' export const CONTROLLER_HELPER: Address = { 1: '0xfa86d43b41Fa7a759c606130cc81970A955ff816', - 3: '', + 3: '0x1561AD75Fc7382C33819e63A4787b6F362D8152f', 421611: '', 31337: '', } From 8e11f527e8de9faab8e4d0a2b93251f1805e06cf Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 22 Jun 2022 23:32:33 -0700 Subject: [PATCH 18/82] tester button --- packages/frontend/pages/lp.tsx | 35 +++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index 53bb73bd7..70b959fb6 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -1,4 +1,4 @@ -import { createStyles, makeStyles } from '@material-ui/core' +import { Button, createStyles, makeStyles } from '@material-ui/core' import Typography from '@material-ui/core/Typography' import Image from 'next/image' import React, { useState } from 'react' @@ -15,6 +15,9 @@ import { SqueethTab, SqueethTabs } from '@components/Tabs' import { useETHPrice } from '@hooks/useETHPrice' import { supportedNetworkAtom } from 'src/state/wallet/atoms' import { useAtomValue } from 'jotai' +import { useOpenPositionDeposit } from 'src/state/lp/hooks' +import BigNumber from 'bignumber.js' +import useAppCallback from '@hooks/useAppCallback' const useStyles = makeStyles((theme) => createStyles({ @@ -73,6 +76,13 @@ const useStyles = makeStyles((theme) => chartNav: { border: `1px solid ${theme.palette.primary.main}30`, }, + buttonTest: { + marginTop: theme.spacing(1), + backgroundColor: theme.palette.success.main, + '&:hover': { + backgroundColor: theme.palette.success.dark, + }, + }, }), ) @@ -82,6 +92,16 @@ export function LPCalculator() { const ethPrice = useETHPrice() const [lpType, setLpType] = useState(0) const supportedNetwork = useAtomValue(supportedNetworkAtom) + const openLPPosition = useOpenPositionDeposit() + + const openPos = useAppCallback(async () => { + try { + await openLPPosition(new BigNumber(50), -887220, 887220, () => {}) + } catch (e) { + console.log(e) + } + }, []) + return (
@@ -155,6 +175,19 @@ export function LPCalculator() { contracts are experimental technology and we encourage caution only risking funds you can afford to lose. + + Testing One Click LP Hooks + +
) : (
From 40f1110c89fe7d61c3f78afd1b5632f9fa56bc54 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Mon, 27 Jun 2022 11:07:46 -0700 Subject: [PATCH 19/82] remove flashloan fee for open --- packages/frontend/src/state/lp/hooks.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 0e5f1090a..272e5da07 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -4,7 +4,7 @@ import { fromTokenAmount } from '@utils/calculations' import { useAtom, useAtomValue } from 'jotai' import { addressesAtom, isWethToken0Atom } from '../positions/atoms' import BigNumber from 'bignumber.js' -import { BIG_ZERO, INDEX_SCALE, OSQUEETH_DECIMALS } from '@constants/index' +import { BIG_ZERO, INDEX_SCALE, OSQUEETH_DECIMALS, UNI_POOL_FEES } from '@constants/index' import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom } from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' import { addressAtom } from '../wallet/atoms' @@ -101,7 +101,6 @@ export const useOpenPositionDeposit = () => { // Do we want to hardcode a 150% collateralization ratio? const collateralToMint = ethDebt.multipliedBy(3).div(2) const collateralToLp = mintWSqueethAmount.multipliedBy(squeethPrice) - const flashloanFee = collateralToMint.multipliedBy(9).div(1000) const lowerTick = nearestUsableTick(lowerTickInput, 3000) const upperTick = nearestUsableTick(upperTickInput, 3000) @@ -126,7 +125,7 @@ export const useOpenPositionDeposit = () => { return handleTransaction( contract.methods.flashloanWMintLpDepositNft(flashloanWMintDepositNftParams).send({ from: address, - value: collateralToLp.plus(flashloanFee).toFixed(0), + value: collateralToLp.toFixed(0), }), onTxConfirmed, ) From 931d94d1ef75bac5dbee2e69d514d017bc7cfad9 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Mon, 27 Jun 2022 20:02:51 -0700 Subject: [PATCH 20/82] fixing controllerhelper address --- packages/frontend/src/constants/address.ts | 2 +- packages/frontend/src/state/lp/hooks.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/constants/address.ts b/packages/frontend/src/constants/address.ts index 6c4e0fd6e..e72239ca1 100644 --- a/packages/frontend/src/constants/address.ts +++ b/packages/frontend/src/constants/address.ts @@ -127,7 +127,7 @@ export const ZERO_ADDR = '0x0000000000000000000000000000000000000000' export const CONTROLLER_HELPER: Address = { 1: '0xfa86d43b41Fa7a759c606130cc81970A955ff816', - 3: '0x1561AD75Fc7382C33819e63A4787b6F362D8152f', + 3: '0x7e9C5490e91F93529c6480B46a59D738F6bcEa43', 421611: '', 31337: '', } diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 272e5da07..c461a5199 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -95,11 +95,11 @@ export const useOpenPositionDeposit = () => { const openPositionDeposit = useAppCallback( async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { const squeethPrice = await getTwapSqueethPrice() - console.log('squeeth price', squeethPrice.toString()) const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) const ethDebt = await getDebtAmount(mintWSqueethAmount) // Do we want to hardcode a 150% collateralization ratio? const collateralToMint = ethDebt.multipliedBy(3).div(2) + console.log('squeeth price', squeethPrice.toString()) const collateralToLp = mintWSqueethAmount.multipliedBy(squeethPrice) const lowerTick = nearestUsableTick(lowerTickInput, 3000) @@ -130,7 +130,7 @@ export const useOpenPositionDeposit = () => { onTxConfirmed, ) }, - [], + [address, squeethPool, contract], ) return openPositionDeposit } From 72bbfdef3d326715f7df6f053f6e89139dce471f Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Mon, 27 Jun 2022 21:01:05 -0700 Subject: [PATCH 21/82] add vault id as open param --- packages/frontend/src/state/lp/hooks.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index c461a5199..120f01fe4 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -18,6 +18,7 @@ import { useUpdateAtom } from 'jotai/utils' import { lowerTickAtom, upperTickAtom } from './atoms' import { useMemo } from 'react' import { useGetDebtAmount, useGetTwapEthPrice, useGetTwapSqueethPrice } from '../controller/hooks' +import { useFirstValidVault } from '../positions/hooks' /*** CONSTANTS ***/ const one = new BigNumber(10).pow(18) @@ -93,13 +94,13 @@ export const useOpenPositionDeposit = () => { const getTwapSqueethPrice = useGetTwapSqueethPrice() const getDebtAmount = useGetDebtAmount() const openPositionDeposit = useAppCallback( - async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { + async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, vaultID: number, onTxConfirmed?: () => void) => { const squeethPrice = await getTwapSqueethPrice() const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) const ethDebt = await getDebtAmount(mintWSqueethAmount) // Do we want to hardcode a 150% collateralization ratio? - const collateralToMint = ethDebt.multipliedBy(3).div(2) console.log('squeeth price', squeethPrice.toString()) + const collateralToMint = ethDebt.multipliedBy(3).div(2) const collateralToLp = mintWSqueethAmount.multipliedBy(squeethPrice) const lowerTick = nearestUsableTick(lowerTickInput, 3000) @@ -107,7 +108,7 @@ export const useOpenPositionDeposit = () => { const flashloanWMintDepositNftParams = { wPowerPerpPool: squeethPool, - vaultId: 0, + vaultId: vaultID, wPowerPerpAmount: mintWSqueethAmount.toFixed(0), collateralToDeposit: collateralToMint.toFixed(0), collateralToFlashloan: collateralToMint.toFixed(0), From a45f1361c10d7c0ab1aa298094382b880db595ff Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Mon, 27 Jun 2022 23:48:26 -0700 Subject: [PATCH 22/82] debugging collect fees --- packages/frontend/src/state/lp/hooks.ts | 29 +++++++++++++++---------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 120f01fe4..e3e115982 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -12,12 +12,12 @@ import { normFactorAtom } from '../controller/atoms' import { Price, Token } from '@uniswap/sdk-core' import { useHandleTransaction } from '../wallet/hooks' import { squeethPriceeAtom, squeethTokenAtom, wethPriceAtom, wethTokenAtom } from '../squeethPool/atoms' -import ethers from 'ethers' +import { ethers } from 'ethers' import { useGetSellQuote } from '../squeethPool/hooks' import { useUpdateAtom } from 'jotai/utils' import { lowerTickAtom, upperTickAtom } from './atoms' import { useMemo } from 'react' -import { useGetDebtAmount, useGetTwapEthPrice, useGetTwapSqueethPrice } from '../controller/hooks' +import { useGetDebtAmount, useGetTwapEthPrice, useGetTwapSqueethPrice, useGetVault } from '../controller/hooks' import { useFirstValidVault } from '../positions/hooks' /*** CONSTANTS ***/ @@ -145,9 +145,11 @@ export const useCollectFees = () => { const handleTransaction = useHandleTransaction() const positionManager = useAtomValue(nftManagerContractAtom) const getDebtAmount = useGetDebtAmount() - const collectFees = useAppCallback(async (vaultId: BigNumber, onTxConfirmed?: () => void) => { - const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId - const vaultBefore = await controllerContract?.methods.vaults(vaultId) + const getVault = useGetVault() + const collectFees = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { + const vaultBefore = await getVault(vaultId) + const uniTokenId = vaultBefore?.NFTCollateralId + if ( !controllerContract || !controllerHelperContract || @@ -157,24 +159,27 @@ export const useCollectFees = () => { !vaultBefore.shortAmount ) return - const debtInEth = await getDebtAmount(vaultBefore.shortAmount) - const collateralToFlashloan = debtInEth.multipliedBy(1.5) - const amount0Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1) - const amount1Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1) + const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + const debtInEth = await getDebtAmount(shortAmount) + const collateralToFlashloan = debtInEth.multipliedBy(1.5) + const amount0Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1).toFixed(0) + const amount1Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1).toFixed(0) + console.log([uniTokenId, amount0Max, amount1Max]) + // console.log(amount0Max.toFixed(0)) const abiCoder = new ethers.utils.AbiCoder() const rebalanceLpInVaultParams = [ { - rebalanceLpInVaultType: new BigNumber(6), + rebalanceLpInVaultType: "6", // CollectFees data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [uniTokenId, amount0Max, amount1Max]), }, ] - + console.log(collateralToFlashloan.toFixed(0)) await controllerContract.methods.updateOperator(vaultId, controllerHelper) return handleTransaction( await controllerHelperContract.methods - .rebalanceLpInVault(vaultId, collateralToFlashloan, rebalanceLpInVaultParams) + .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) .send({ from: address, }), From e5d43a5a3f22ca5e6bfa3ffe0131758c16d99cac Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 28 Jun 2022 20:24:28 -0700 Subject: [PATCH 23/82] getting position manager --- packages/frontend/src/state/lp/hooks.ts | 99 ++++++++++++++++++++----- 1 file changed, 80 insertions(+), 19 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index e3e115982..faa27fd1c 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -16,7 +16,7 @@ import { ethers } from 'ethers' import { useGetSellQuote } from '../squeethPool/hooks' import { useUpdateAtom } from 'jotai/utils' import { lowerTickAtom, upperTickAtom } from './atoms' -import { useMemo } from 'react' +import { useCallback, useMemo } from 'react' import { useGetDebtAmount, useGetTwapEthPrice, useGetTwapSqueethPrice, useGetVault } from '../controller/hooks' import { useFirstValidVault } from '../positions/hooks' @@ -35,35 +35,44 @@ export const useClosePosition = () => { const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) const { controllerHelper } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) - const positionManager = useAtomValue(nftManagerContractAtom) const handleTransaction = useHandleTransaction() const getTwapSqueethPrice = useGetTwapSqueethPrice() const getDebtAmount = useGetDebtAmount() - const closePosition = useAppCallback(async (vaultId: BigNumber, onTxConfirmed?: () => void) => { - const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId - const vaultBefore = await controllerContract?.methods.vaults(vaultId) + const getVault = useGetVault() + const getPosition = useGetPosition() + const closePosition = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { + const vaultBefore = await getVault(vaultId) + console.log(vaultBefore) + const uniTokenId = vaultBefore?.NFTCollateralId + const position = await getPosition(uniTokenId) + if ( !controllerContract || !controllerHelperContract || !address || - !positionManager || + !position || !vaultBefore || !vaultBefore.shortAmount ) return - const debtInEth = await getDebtAmount(vaultBefore.shortAmount) + + const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + console.log("shortAmount", shortAmount) + const debtInEth = await getDebtAmount(shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(1.5) // What should we set as slippage const slippage = new BigNumber(3).multipliedBy(new BigNumber(10).pow(16)) const squeethPrice = await getTwapSqueethPrice() - const limitPriceEthPerPowerPerp = squeethPrice.multipliedBy(one.minus(slippage)).div(one) - const positionBefore = await positionManager.methods.positions(uniTokenId) + console.log("squeethPrice", squeethPrice.toString()) + const limitPriceEthPerPowerPerp = squeethPrice.multipliedBy(one.minus(slippage)) + // const positionBefore = await positionManager.methods.positions(uniTokenId) + console.log("position", position.liquidity) const flashloanCloseVaultLpNftParam = { - vaultId: vaultId, + vaultId: vaultId.toFixed(0), tokenId: uniTokenId, - liquidity: positionBefore.liquidity, + liquidity: position.liquidity, liquidityPercentage: fromTokenAmount(1, 18).toFixed(0), - wPowerPerpAmountToBurn: vaultBefore.shortAmount.toFixed(0), + wPowerPerpAmountToBurn: shortAmount.toFixed(0), collateralToFlashloan: collateralToFlashloan.toFixed(0), collateralToWithdraw: 0, limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp.toFixed(0), @@ -72,8 +81,9 @@ export const useClosePosition = () => { poolFee: 3000, burnExactRemoved: false, } + console.log(flashloanCloseVaultLpNftParam) - await controllerContract.methods.updateOperator(vaultId, controllerHelper) + // await controllerContract.methods.updateOperator(vaultId, controllerHelper) return handleTransaction( await controllerHelperContract.methods.flashloanCloseVaultLpNft(flashloanCloseVaultLpNftParam).send({ @@ -148,6 +158,7 @@ export const useCollectFees = () => { const getVault = useGetVault() const collectFees = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) + console.log(vaultBefore) const uniTokenId = vaultBefore?.NFTCollateralId if ( @@ -161,25 +172,45 @@ export const useCollectFees = () => { return const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + console.log("shortAmount", shortAmount) const debtInEth = await getDebtAmount(shortAmount) + console.log("debtInEth", debtInEth) const collateralToFlashloan = debtInEth.multipliedBy(1.5) + console.log("collateralToFlashloan", collateralToFlashloan) const amount0Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1).toFixed(0) const amount1Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1).toFixed(0) console.log([uniTokenId, amount0Max, amount1Max]) // console.log(amount0Max.toFixed(0)) const abiCoder = new ethers.utils.AbiCoder() + // const rebalanceLpInVaultParams = [ + // { + // rebalanceLpInVaultType: new BigNumber(6).toFixed(0), + // // CollectFees + // data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [Number(uniTokenId), amount0Max, amount1Max]), + // }, + // { + // rebalanceLpInVaultType: new BigNumber(7).toFixed(0), + // // DepositExistingNftParams + // data: abiCoder.encode(["uint256"], [Number(uniTokenId)]) + // } + // ] + // console.log(rebalanceLpInVaultParams) + // await controllerContract.methods.updateOperator(vaultId, controllerHelper) + const rebalanceLpInVaultParams = [ { - rebalanceLpInVaultType: "6", - // CollectFees - data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [uniTokenId, amount0Max, amount1Max]), + rebalanceLpInVaultType: new BigNumber(6).toFixed(0), + data: '0x00000000000000000000000000000000000000000000000000000000000311220000000000000000000000000000000000000000000000001bc16d674ec7ffff0000000000000000000000000000000000000000000000001bc16d674ec7ffff' }, + { + rebalanceLpInVaultType: new BigNumber(7).toFixed(0), + data: '0x0000000000000000000000000000000000000000000000000000000000031122' + } ] - console.log(collateralToFlashloan.toFixed(0)) - await controllerContract.methods.updateOperator(vaultId, controllerHelper) + console.log("hi") return handleTransaction( await controllerHelperContract.methods - .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) + .rebalanceLpInVault("673", '0', rebalanceLpInVaultParams) .send({ from: address, }), @@ -477,3 +508,33 @@ export default function useIsTickAtLimit( [feeAmount, tickLower, tickUpper], ) } + +export const useGetPosition = () => { + const contract = useAtomValue(nftManagerContractAtom) + + const getPosition = useCallback( + async (uniTokenId: number) => { + if (!contract) return null + const position = await contract.methods.positions(uniTokenId).call() + const { nonce, operator, token0, token1, fee, tickLower, tickUpper, liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128, tokensOwed0, tokensOwed1 } = position + + return { + nonce, + operator, + token0, + token1, + fee, + tickLower, + tickUpper, + liquidity, + feeGrowthInside0LastX128, + feeGrowthInside1LastX128, + tokensOwed0, + tokensOwed1 + } + }, + [contract], + ) + + return getPosition +} From 472d3f34e15ea4409fe95e30fa19436c49dd0d1a Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 28 Jun 2022 20:34:44 -0700 Subject: [PATCH 24/82] debugged close position (with no burning) --- packages/frontend/src/state/lp/hooks.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index faa27fd1c..cd4146905 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -33,7 +33,6 @@ export enum Bound { export const useClosePosition = () => { const address = useAtomValue(addressAtom) const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) - const { controllerHelper } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() const getTwapSqueethPrice = useGetTwapSqueethPrice() @@ -57,16 +56,13 @@ export const useClosePosition = () => { return const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) - console.log("shortAmount", shortAmount) const debtInEth = await getDebtAmount(shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(1.5) - // What should we set as slippage const slippage = new BigNumber(3).multipliedBy(new BigNumber(10).pow(16)) const squeethPrice = await getTwapSqueethPrice() - console.log("squeethPrice", squeethPrice.toString()) const limitPriceEthPerPowerPerp = squeethPrice.multipliedBy(one.minus(slippage)) + // const positionBefore = await positionManager.methods.positions(uniTokenId) - console.log("position", position.liquidity) const flashloanCloseVaultLpNftParam = { vaultId: vaultId.toFixed(0), tokenId: uniTokenId, @@ -79,11 +75,8 @@ export const useClosePosition = () => { amount0Min: 0, amount1Min: 0, poolFee: 3000, - burnExactRemoved: false, + burnExactRemoved: true, } - console.log(flashloanCloseVaultLpNftParam) - - // await controllerContract.methods.updateOperator(vaultId, controllerHelper) return handleTransaction( await controllerHelperContract.methods.flashloanCloseVaultLpNft(flashloanCloseVaultLpNftParam).send({ @@ -91,7 +84,7 @@ export const useClosePosition = () => { }), onTxConfirmed, ) - }, []) + }, [address, controllerHelperContract, controllerContract]) return closePosition } From 192b87d06cbe1c19e7a08772c2ace23eace4070e Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 29 Jun 2022 16:36:24 -0700 Subject: [PATCH 25/82] close position with quoter limit price --- packages/frontend/src/state/lp/hooks.ts | 53 ++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index cd4146905..3f7313ca4 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -5,7 +5,7 @@ import { useAtom, useAtomValue } from 'jotai' import { addressesAtom, isWethToken0Atom } from '../positions/atoms' import BigNumber from 'bignumber.js' import { BIG_ZERO, INDEX_SCALE, OSQUEETH_DECIMALS, UNI_POOL_FEES } from '@constants/index' -import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom } from '../contracts/atoms' +import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom, quoterContractAtom } from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' import { addressAtom } from '../wallet/atoms' import { normFactorAtom } from '../controller/atoms' @@ -13,7 +13,7 @@ import { Price, Token } from '@uniswap/sdk-core' import { useHandleTransaction } from '../wallet/hooks' import { squeethPriceeAtom, squeethTokenAtom, wethPriceAtom, wethTokenAtom } from '../squeethPool/atoms' import { ethers } from 'ethers' -import { useGetSellQuote } from '../squeethPool/hooks' +import { useGetBuyQuote, useGetSellQuote } from '../squeethPool/hooks' import { useUpdateAtom } from 'jotai/utils' import { lowerTickAtom, upperTickAtom } from './atoms' import { useCallback, useMemo } from 'react' @@ -39,7 +39,11 @@ export const useClosePosition = () => { const getDebtAmount = useGetDebtAmount() const getVault = useGetVault() const getPosition = useGetPosition() + const getLimitEth = useGetLimitEth() + const getSellQuote = useGetSellQuote() const closePosition = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { + // const limitEth = await getLimitEth(new BigNumber(5)) + // console.log("limitEth", limitEth) const vaultBefore = await getVault(vaultId) console.log(vaultBefore) const uniTokenId = vaultBefore?.NFTCollateralId @@ -60,24 +64,30 @@ export const useClosePosition = () => { const collateralToFlashloan = debtInEth.multipliedBy(1.5) const slippage = new BigNumber(3).multipliedBy(new BigNumber(10).pow(16)) const squeethPrice = await getTwapSqueethPrice() - const limitPriceEthPerPowerPerp = squeethPrice.multipliedBy(one.minus(slippage)) + // const limitPriceEthPerPowerPerp = squeethPrice.multipliedBy(one.minus(slippage)) + const limitEth = await getLimitEth(shortAmount) + // console.log("limitEThQuote", limitEthQuote.amountOut.multipliedBy(new BigNumber(10).pow(14)).toFixed(0)) + // console.log("limitEth", limitEth.toFixed(0)) + console.log("limitPriceEthPerPowerPerp", limitEth) + console.log("squeethPrice", squeethPrice) - // const positionBefore = await positionManager.methods.positions(uniTokenId) const flashloanCloseVaultLpNftParam = { - vaultId: vaultId.toFixed(0), + vaultId: vaultId, tokenId: uniTokenId, liquidity: position.liquidity, liquidityPercentage: fromTokenAmount(1, 18).toFixed(0), wPowerPerpAmountToBurn: shortAmount.toFixed(0), collateralToFlashloan: collateralToFlashloan.toFixed(0), collateralToWithdraw: 0, - limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp.toFixed(0), + limitPriceEthPerPowerPerp: limitEth, amount0Min: 0, amount1Min: 0, poolFee: 3000, burnExactRemoved: true, } + console.log("flashloanCloseVaultLpNftParam", flashloanCloseVaultLpNftParam) + return handleTransaction( await controllerHelperContract.methods.flashloanCloseVaultLpNft(flashloanCloseVaultLpNftParam).send({ from: address, @@ -100,6 +110,7 @@ export const useOpenPositionDeposit = () => { async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, vaultID: number, onTxConfirmed?: () => void) => { const squeethPrice = await getTwapSqueethPrice() const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) + console.log("squeethPrice", squeethPrice.toString()) const ethDebt = await getDebtAmount(mintWSqueethAmount) // Do we want to hardcode a 150% collateralization ratio? console.log('squeeth price', squeethPrice.toString()) @@ -531,3 +542,33 @@ export const useGetPosition = () => { return getPosition } + +export const useGetLimitEth = () => { + const contract = useAtomValue(quoterContractAtom) + const {weth, oSqueeth} = useAtomValue(addressesAtom) + + const getLimitEth = useCallback( + async (mintWSqueethAmount: BigNumber) => { + console.log("mintWsqueethAmount", mintWSqueethAmount.toFixed(0)) + console.log("osqueeth", oSqueeth) + console.log("weth", weth) + console.log("fee", 3000) + if (!contract) return null + + const QuoteExactInputSingleParams = { + tokenIn: oSqueeth, + tokenOut: weth, + amountIn: mintWSqueethAmount.toFixed(0), + fee: 3000, + sqrtPriceLimitX96: 0 + } + + const limitEth = await contract.methods.quoteExactInputSingle(QuoteExactInputSingleParams).call() + return limitEth.amountOut + }, + [contract, weth, oSqueeth], + ) + + return getLimitEth +} + From 96dc6749526b12b53d43f3e69eab15280383333f Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 29 Jun 2022 17:20:23 -0700 Subject: [PATCH 26/82] collect fees works merge --- packages/frontend/src/abis/quoter.json | 2 +- .../frontend/src/state/contracts/atoms.ts | 8 ++++ packages/frontend/src/state/lp/hooks.ts | 44 ++++--------------- 3 files changed, 17 insertions(+), 37 deletions(-) diff --git a/packages/frontend/src/abis/quoter.json b/packages/frontend/src/abis/quoter.json index ce1374e69..9a974d621 100644 --- a/packages/frontend/src/abis/quoter.json +++ b/packages/frontend/src/abis/quoter.json @@ -264,4 +264,4 @@ "stateMutability": "view", "type": "function" } -] +] \ No newline at end of file diff --git a/packages/frontend/src/state/contracts/atoms.ts b/packages/frontend/src/state/contracts/atoms.ts index 2a752f666..f1758fda9 100644 --- a/packages/frontend/src/state/contracts/atoms.ts +++ b/packages/frontend/src/state/contracts/atoms.ts @@ -11,6 +11,7 @@ import routerABI from '../../abis/swapRouter.json' import uniABI from '../../abis/uniswapPool.json' import shortAbi from '../../abis/shortHelper.json' import crabMigrationAbi from '../../abis/crabMigration.json' +import quoterAbi from '../../abis/quoter.json' import { addressesAtom } from '../positions/atoms' import { web3Atom } from '../wallet/atoms' @@ -42,6 +43,13 @@ export const nftManagerContractAtom = atom((get) => { return getContract(web3, nftManager, positionManagerAbi) }) +export const quoterContractAtom = atom((get) => { + const web3 = get(web3Atom) + const { quoter } = get(addressesAtom) + if (!web3) return null + return getContract(web3, quoter, quoterAbi) +}) + export const swapRouterContractAtom = atom((get) => { const web3 = get(web3Atom) const { swapRouter } = get(addressesAtom) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 3f7313ca4..d14b9ad3e 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -35,12 +35,10 @@ export const useClosePosition = () => { const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() - const getTwapSqueethPrice = useGetTwapSqueethPrice() const getDebtAmount = useGetDebtAmount() const getVault = useGetVault() const getPosition = useGetPosition() const getLimitEth = useGetLimitEth() - const getSellQuote = useGetSellQuote() const closePosition = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { // const limitEth = await getLimitEth(new BigNumber(5)) // console.log("limitEth", limitEth) @@ -62,14 +60,7 @@ export const useClosePosition = () => { const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) const debtInEth = await getDebtAmount(shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(1.5) - const slippage = new BigNumber(3).multipliedBy(new BigNumber(10).pow(16)) - const squeethPrice = await getTwapSqueethPrice() - // const limitPriceEthPerPowerPerp = squeethPrice.multipliedBy(one.minus(slippage)) const limitEth = await getLimitEth(shortAmount) - // console.log("limitEThQuote", limitEthQuote.amountOut.multipliedBy(new BigNumber(10).pow(14)).toFixed(0)) - // console.log("limitEth", limitEth.toFixed(0)) - console.log("limitPriceEthPerPowerPerp", limitEth) - console.log("squeethPrice", squeethPrice) const flashloanCloseVaultLpNftParam = { vaultId: vaultId, @@ -154,7 +145,6 @@ export const useOpenPositionDeposit = () => { export const useCollectFees = () => { const address = useAtomValue(addressAtom) const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) - const { controllerHelper } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() const positionManager = useAtomValue(nftManagerContractAtom) @@ -176,45 +166,27 @@ export const useCollectFees = () => { return const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) - console.log("shortAmount", shortAmount) const debtInEth = await getDebtAmount(shortAmount) - console.log("debtInEth", debtInEth) const collateralToFlashloan = debtInEth.multipliedBy(1.5) - console.log("collateralToFlashloan", collateralToFlashloan) const amount0Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1).toFixed(0) const amount1Max = new BigNumber(2).multipliedBy(new BigNumber(10).pow(18)).minus(1).toFixed(0) - console.log([uniTokenId, amount0Max, amount1Max]) - // console.log(amount0Max.toFixed(0)) const abiCoder = new ethers.utils.AbiCoder() - // const rebalanceLpInVaultParams = [ - // { - // rebalanceLpInVaultType: new BigNumber(6).toFixed(0), - // // CollectFees - // data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [Number(uniTokenId), amount0Max, amount1Max]), - // }, - // { - // rebalanceLpInVaultType: new BigNumber(7).toFixed(0), - // // DepositExistingNftParams - // data: abiCoder.encode(["uint256"], [Number(uniTokenId)]) - // } - // ] - // console.log(rebalanceLpInVaultParams) - // await controllerContract.methods.updateOperator(vaultId, controllerHelper) - const rebalanceLpInVaultParams = [ { - rebalanceLpInVaultType: new BigNumber(6).toFixed(0), - data: '0x00000000000000000000000000000000000000000000000000000000000311220000000000000000000000000000000000000000000000001bc16d674ec7ffff0000000000000000000000000000000000000000000000001bc16d674ec7ffff' + rebalanceLpInVaultType: new BigNumber(6).toFixed(0), + // CollectFees + data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [Number(uniTokenId), amount0Max, amount1Max]), }, { - rebalanceLpInVaultType: new BigNumber(7).toFixed(0), - data: '0x0000000000000000000000000000000000000000000000000000000000031122' + rebalanceLpInVaultType: new BigNumber(7).toFixed(0), + // DepositExistingNftParams + data: abiCoder.encode(["uint256"], [Number(uniTokenId)]) } ] - console.log("hi") + return handleTransaction( await controllerHelperContract.methods - .rebalanceLpInVault("673", '0', rebalanceLpInVaultParams) + .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) .send({ from: address, }), From c92b3628d7a00f120de95f76182ea1ad5b20a77c Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 30 Jun 2022 00:25:51 -0700 Subject: [PATCH 27/82] rebalance tx --- packages/frontend/src/state/lp/hooks.ts | 215 +++++++++++++----------- 1 file changed, 113 insertions(+), 102 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index d14b9ad3e..fb8045494 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -4,10 +4,10 @@ import { fromTokenAmount } from '@utils/calculations' import { useAtom, useAtomValue } from 'jotai' import { addressesAtom, isWethToken0Atom } from '../positions/atoms' import BigNumber from 'bignumber.js' -import { BIG_ZERO, INDEX_SCALE, OSQUEETH_DECIMALS, UNI_POOL_FEES } from '@constants/index' +import { BIG_ZERO, INDEX_SCALE, OSQUEETH_DECIMALS, UNI_POOL_FEES, WETH_DECIMALS } from '@constants/index' import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom, quoterContractAtom } from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' -import { addressAtom } from '../wallet/atoms' +import { addressAtom, web3Atom } from '../wallet/atoms' import { normFactorAtom } from '../controller/atoms' import { Price, Token } from '@uniswap/sdk-core' import { useHandleTransaction } from '../wallet/hooks' @@ -40,10 +40,7 @@ export const useClosePosition = () => { const getPosition = useGetPosition() const getLimitEth = useGetLimitEth() const closePosition = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { - // const limitEth = await getLimitEth(new BigNumber(5)) - // console.log("limitEth", limitEth) const vaultBefore = await getVault(vaultId) - console.log(vaultBefore) const uniTokenId = vaultBefore?.NFTCollateralId const position = await getPosition(uniTokenId) @@ -147,19 +144,16 @@ export const useCollectFees = () => { const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() - const positionManager = useAtomValue(nftManagerContractAtom) const getDebtAmount = useGetDebtAmount() const getVault = useGetVault() const collectFees = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) - console.log(vaultBefore) const uniTokenId = vaultBefore?.NFTCollateralId if ( !controllerContract || !controllerHelperContract || !address || - !positionManager || !vaultBefore || !vaultBefore.shortAmount ) @@ -210,20 +204,26 @@ export const useRebalanceVault = () => { const { controllerHelper, squeethPool } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() - const positionManager = useAtomValue(nftManagerContractAtom) const isWethToken0 = useAtomValue(isWethToken0Atom) + const web3 = useAtomValue(web3Atom) const getSellQuote = useGetSellQuote() const getDebtAmount = useGetDebtAmount() + const getVault = useGetVault() + const getPosition = useGetPosition() + const getTotalSupply = useGetTotalSupply() + const getTokenByIndex = useGetTokenByIndex() + const getDecreaseLiquidity = useGetDecreaseLiquidity() + const getLimitEth = useGetLimitEth() const rebalanceVault = useAppCallback( - async (vaultId: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { - if (!controllerContract || !controllerHelperContract || !address || !positionManager) return - const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId - const positionBefore = await positionManager.methods.positions(uniTokenId) - const vaultBefore = await controllerContract?.methods.vaults(vaultId) - const debtInEth = await getDebtAmount(vaultBefore.shortAmount) + async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { + const vaultBefore = await getVault(vaultId) + const uniTokenId = vaultBefore?.NFTCollateralId + const position = await getPosition(uniTokenId) + console.log(position) + if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore ) return + const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + const debtInEth = await getDebtAmount(shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(1.5) - const tokenIndex = await positionManager.methods.totalSupply() - const tokenId = await positionManager.methods.tokenByIndex(tokenIndex.sub(1)) const amount0Min = new BigNumber(0) const amount1Min = new BigNumber(0) @@ -231,33 +231,31 @@ export const useRebalanceVault = () => { const upperTick = nearestUsableTick(upperTickInput, 3000) // Get current LPpositions - const [amount0, amount1] = await positionManager.methods.decreaseLiquidity({ - tokenId: tokenId, - liquidity: positionBefore.liquidity, - amount0Min: 0, - amount1Min: 0, - deadline: Math.floor(Date.now() / 1000 + 1800), - }) + const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) + const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 // Estimate proceeds from liquidating squeeth in LP - const ethAmountOutFromSwap = getSellQuote(wPowerPerpAmountInLPBefore) + const wPowerPerpAmountInLPBeforeVal = fromTokenAmount(wPowerPerpAmountInLPBefore, OSQUEETH_DECIMALS) + const ethAmountOutFromSwap = await getLimitEth(wPowerPerpAmountInLPBeforeVal) - // Estimate of new LP with 0.01 weth safety margin - const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap) + // Estimate of new LP + const wethAmountInLPBeforeVal = fromTokenAmount(wethAmountInLPBefore, WETH_DECIMALS) + const wethAmountToLP = wethAmountInLPBeforeVal.plus(ethAmountOutFromSwap).toFixed(0) + console.log("wethAmountToLP", wethAmountToLP) const abiCoder = new ethers.utils.AbiCoder() const rebalanceLpInVaultParams = [ { // Liquidate LP - rebalanceLpInVaultType: new BigNumber(1), // DecreaseLpLiquidity: + rebalanceLpInVaultType: new BigNumber(1).toFixed(0), // DecreaseLpLiquidity: // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min] data: abiCoder.encode( ['uint256', 'uint256', 'uint256', 'uint128', 'uint128'], [ - tokenId, - positionBefore.liquidity, + uniTokenId, + position.liquidity, new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toFixed(0), new BigNumber(0).toFixed(0), new BigNumber(0).toFixed(0), @@ -266,13 +264,13 @@ export const useRebalanceVault = () => { }, { // Deposit into vault and mint - rebalanceLpInVaultType: new BigNumber(2).toString(), // DepositIntoVault + rebalanceLpInVaultType: new BigNumber(2).toFixed(0), // DepositIntoVault // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit] data: abiCoder.encode(['uint256', 'uint256'], [wPowerPerpAmountInLPBefore, wethAmountInLPBefore]), }, { // Withdraw from vault - rebalanceLpInVaultType: new BigNumber(3), // WithdrawFromVault + rebalanceLpInVaultType: new BigNumber(3).toFixed(0), // WithdrawFromVault // withdrawFromVault: [wPowerPerpToBurn, collateralToWithdraw, burnExactRemoved ] data: abiCoder.encode( ['uint256', 'uint256', 'bool'], @@ -281,7 +279,7 @@ export const useRebalanceVault = () => { }, { // Mint new LP - rebalanceLpInVaultType: new BigNumber(4).toString(), // MintNewLP + rebalanceLpInVaultType: new BigNumber(4).toFixed(0), // MintNewLP // lpWPowerPerpPool: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ] data: abiCoder.encode( ['address', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'], @@ -292,8 +290,8 @@ export const useRebalanceVault = () => { new BigNumber(0).toFixed(0), new BigNumber(0).toFixed(0), wethAmountToLP, - amount0Min, - amount1Min, + amount0Min.toFixed(0), + amount1Min.toFixed(0), lowerTick, upperTick, ], @@ -301,10 +299,11 @@ export const useRebalanceVault = () => { }, ] - await controllerContract.methods.updateOperator(vaultId, controllerHelper) + console.log("collateralToFlashloan", collateralToFlashloan.toString()) + return handleTransaction( await controllerHelperContract.methods - .rebalanceLpInVault(vaultId, collateralToFlashloan, rebalanceLpInVaultParams) + .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) .send({ from: address, }), @@ -335,22 +334,31 @@ export const useRebalanceGeneralSwap = () => { const vaultBefore = await controllerContract?.methods.vaults(vaultId) const debtInEth = await getDebtAmount(vaultBefore.shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(1.5) + console.log("a") const tokenIndex = await positionManager.methods.totalSupply() + console.log("b") const tokenId = await positionManager.methods.tokenByIndex(tokenIndex.sub(1)) + console.log("c") const amount0Min = new BigNumber(0) const amount1Min = new BigNumber(0) const lowerTick = nearestUsableTick(lowerTickInput, 3000) const upperTick = nearestUsableTick(upperTickInput, 3000) - + console.log("tokenid", tokenId) + console.log("token index", tokenIndex) + console.log("beep") // Get current LPpositions const [amount0, amount1] = await positionManager.methods.decreaseLiquidity({ tokenId: tokenId, liquidity: positionBefore.liquidity, - amount0Min: 0, - amount1Min: 0, - deadline: Math.floor(Date.now() / 1000 + 1800), + amount0Min: amount0Min, + amount1Min: amount1Min, + deadline: Math.floor(Date.now() / 1000) + 1800, }) + + // console.log("amount 0", amount0) + // console.log("amount 1", amount1) + const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 @@ -424,66 +432,6 @@ export const useRebalanceGeneralSwap = () => { } /*** GETTERS ***/ -// Get next tick price -export const useGetNextTickPrice = () => { - const setLowerTick = useUpdateAtom(lowerTickAtom) - const setUpperTick = useUpdateAtom(upperTickAtom) - const lowerTick = useAtomValue(lowerTickAtom) - const upperTick = useAtomValue(upperTickAtom) - const isWethToken0 = useAtomValue(isWethToken0Atom) - const squeethToken = useAtomValue(squeethTokenAtom) - const wethToken = useAtomValue(wethTokenAtom) - const getNextTickPrice = useAppCallback(async (getHigherTick: boolean, isUpperTick: boolean) => { - const atLimit = useIsTickAtLimit(3000, lowerTick.toNumber(), upperTick.toNumber()) - - if (isUpperTick) { - const newUpperTick = !getHigherTick - ? upperTick.minus(TICK_SPACINGS[3000]) - : !atLimit - ? upperTick.plus(TICK_SPACINGS[3000]) - : null - if (newUpperTick) { - setUpperTick(newUpperTick) - return isWethToken0 - ? tickToPrice(wethToken!, squeethToken!, newUpperTick.toNumber()) - : tickToPrice(squeethToken!, wethToken!, newUpperTick.toNumber()) - } - } else { - const newLowerTick = getHigherTick - ? lowerTick.plus(TICK_SPACINGS[3000]) - : !atLimit - ? lowerTick.minus(TICK_SPACINGS[3000]) - : null - if (newLowerTick) { - setLowerTick(newLowerTick) - return isWethToken0 - ? tickToPrice(wethToken!, squeethToken!, newLowerTick.toNumber()) - : tickToPrice(squeethToken!, wethToken!, newLowerTick.toNumber()) - } - } - }, []) - return getNextTickPrice -} - -export default function useIsTickAtLimit( - feeAmount: FeeAmount | undefined, - tickLower: number | undefined, - tickUpper: number | undefined, -) { - return useMemo( - () => ({ - [Bound.LOWER]: - feeAmount && tickLower - ? tickLower === nearestUsableTick(TickMath.MIN_TICK, TICK_SPACINGS[feeAmount as FeeAmount]) - : undefined, - [Bound.UPPER]: - feeAmount && tickUpper - ? tickUpper === nearestUsableTick(TickMath.MAX_TICK, TICK_SPACINGS[feeAmount as FeeAmount]) - : undefined, - }), - [feeAmount, tickLower, tickUpper], - ) -} export const useGetPosition = () => { const contract = useAtomValue(nftManagerContractAtom) @@ -493,7 +441,7 @@ export const useGetPosition = () => { if (!contract) return null const position = await contract.methods.positions(uniTokenId).call() const { nonce, operator, token0, token1, fee, tickLower, tickUpper, liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128, tokensOwed0, tokensOwed1 } = position - + console.log("unitokenid", uniTokenId) return { nonce, operator, @@ -515,6 +463,64 @@ export const useGetPosition = () => { return getPosition } +export const useGetTotalSupply = () => { + const contract = useAtomValue(nftManagerContractAtom) + + const getTotalSupply = useCallback( + async () => { + if (!contract) return null + const totalSupply = await contract.methods.totalSupply().call() + + return totalSupply + }, + [contract], + ) + + return getTotalSupply +} + +export const useGetTokenByIndex = () => { + const contract = useAtomValue(nftManagerContractAtom) + + const getTokenByIndex = useCallback( + async (index: BigNumber) => { + if (!contract) return null + const tokenByIndex = await contract.methods.tokenByIndex(index.toFixed(0)).call() + + return tokenByIndex + }, + [contract], + ) + + return getTokenByIndex +} + +export const useGetDecreaseLiquidity = () => { + const contract = useAtomValue(nftManagerContractAtom) + + const getDecreaseLiquiduity = useCallback( + async (tokenId: number, liquidity: number, amount0Min: number, amount1Min: number, deadline: number) => { + if (!contract) return null + const DecreaseLiquidityParams = { + tokenId, + liquidity, + amount0Min, + amount1Min, + deadline, + } + console.log("DecreaseLiquidityParams", DecreaseLiquidityParams) + + const decreaseLiquidity = await contract.methods.decreaseLiquidity(DecreaseLiquidityParams).call() + + return decreaseLiquidity + }, + [contract], + ) + + return getDecreaseLiquiduity +} + + export const useGetLimitEth = () => { const contract = useAtomValue(quoterContractAtom) const {weth, oSqueeth} = useAtomValue(addressesAtom) @@ -544,3 +550,8 @@ export const useGetLimitEth = () => { return getLimitEth } +// export const getNow = async(provider: any) => { +// const blockNumBefore = await provider.getBlockNumber(); +// const blockBefore = await provider.getBlock(blockNumBefore); +// return blockBefore.timestamp; +// } From fd6f66510e50d5915a0627ef9f6e53aaf5fb1454 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 30 Jun 2022 11:20:44 -0700 Subject: [PATCH 28/82] rebal swap tx --- packages/frontend/src/state/lp/hooks.ts | 114 ++++++++++++------------ 1 file changed, 56 insertions(+), 58 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index fb8045494..4efce6fe5 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -218,6 +218,7 @@ export const useRebalanceVault = () => { async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) const uniTokenId = vaultBefore?.NFTCollateralId + console.log("uniTokenId", uniTokenId) const position = await getPosition(uniTokenId) console.log(position) if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore ) return @@ -233,16 +234,19 @@ export const useRebalanceVault = () => { // Get current LPpositions const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) + console.log("iswethtoken0", isWethToken0) const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 // Estimate proceeds from liquidating squeeth in LP const wPowerPerpAmountInLPBeforeVal = fromTokenAmount(wPowerPerpAmountInLPBefore, OSQUEETH_DECIMALS) const ethAmountOutFromSwap = await getLimitEth(wPowerPerpAmountInLPBeforeVal) + console.log("ethAmountOutFromSwap", ethAmountOutFromSwap) // Estimate of new LP - const wethAmountInLPBeforeVal = fromTokenAmount(wethAmountInLPBefore, WETH_DECIMALS) - const wethAmountToLP = wethAmountInLPBeforeVal.plus(ethAmountOutFromSwap).toFixed(0) + const wethAmountToLP = new BigNumber(wethAmountInLPBefore).plus(ethAmountOutFromSwap).toFixed(0) + console.log("wPowerPerpAmountInLPBefore", wPowerPerpAmountInLPBefore.toString()) + console.log("wethAmountInLPBefore", wethAmountInLPBefore.toString()) console.log("wethAmountToLP", wethAmountToLP) const abiCoder = new ethers.utils.AbiCoder() @@ -256,27 +260,27 @@ export const useRebalanceVault = () => { [ uniTokenId, position.liquidity, - new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toFixed(0), - new BigNumber(0).toFixed(0), - new BigNumber(0).toFixed(0), + fromTokenAmount(1, 18).toFixed(0), + 0, + 0, ], ), }, - { - // Deposit into vault and mint - rebalanceLpInVaultType: new BigNumber(2).toFixed(0), // DepositIntoVault - // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit] - data: abiCoder.encode(['uint256', 'uint256'], [wPowerPerpAmountInLPBefore, wethAmountInLPBefore]), - }, { // Withdraw from vault rebalanceLpInVaultType: new BigNumber(3).toFixed(0), // WithdrawFromVault // withdrawFromVault: [wPowerPerpToBurn, collateralToWithdraw, burnExactRemoved ] data: abiCoder.encode( ['uint256', 'uint256', 'bool'], - [wPowerPerpAmountInLPBefore, wethAmountInLPBefore, false], + [wPowerPerpAmountInLPBefore, wethAmountInLPBefore, true], ), }, + { + // Deposit into vault and mint + rebalanceLpInVaultType: new BigNumber(2).toFixed(0), // DepositIntoVault + // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit] + data: abiCoder.encode(['uint256', 'uint256'], [wPowerPerpAmountInLPBefore, wethAmountInLPBefore]), + }, { // Mint new LP rebalanceLpInVaultType: new BigNumber(4).toFixed(0), // MintNewLP @@ -287,8 +291,8 @@ export const useRebalanceVault = () => { controllerHelper, squeethPool, vaultId, - new BigNumber(0).toFixed(0), - new BigNumber(0).toFixed(0), + 0, + 0, wethAmountToLP, amount0Min.toFixed(0), amount1Min.toFixed(0), @@ -322,81 +326,73 @@ export const useRebalanceGeneralSwap = () => { const { controllerHelper, weth, oSqueeth, squeethPool } = useAtomValue(addressesAtom) const controllerContract = useAtomValue(controllerContractAtom) const handleTransaction = useHandleTransaction() - const positionManager = useAtomValue(nftManagerContractAtom) const isWethToken0 = useAtomValue(isWethToken0Atom) - const getSellQuote = useGetSellQuote() const getDebtAmount = useGetDebtAmount() + const getVault = useGetVault() + const getDecreaseLiquidity = useGetDecreaseLiquidity() + const getPosition = useGetPosition() + const getLimitEth = useGetLimitEth() const rebalanceGeneralSwap = useAppCallback( - async (vaultId: BigNumber, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { - if (!controllerContract || !controllerHelperContract || !address || !positionManager) return - const uniTokenId = (await controllerContract?.methods.vaults(vaultId)).NftCollateralId - const positionBefore = await positionManager.methods.positions(uniTokenId) - const vaultBefore = await controllerContract?.methods.vaults(vaultId) - const debtInEth = await getDebtAmount(vaultBefore.shortAmount) + async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { + const vaultBefore = await getVault(vaultId) + const uniTokenId = vaultBefore?.NFTCollateralId + const position = await getPosition(uniTokenId) + if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore) return + const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + const debtInEth = await getDebtAmount(shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(1.5) - console.log("a") - const tokenIndex = await positionManager.methods.totalSupply() - console.log("b") - const tokenId = await positionManager.methods.tokenByIndex(tokenIndex.sub(1)) - console.log("c") const amount0Min = new BigNumber(0) const amount1Min = new BigNumber(0) const lowerTick = nearestUsableTick(lowerTickInput, 3000) const upperTick = nearestUsableTick(upperTickInput, 3000) - console.log("tokenid", tokenId) - console.log("token index", tokenIndex) - console.log("beep") // Get current LPpositions - const [amount0, amount1] = await positionManager.methods.decreaseLiquidity({ - tokenId: tokenId, - liquidity: positionBefore.liquidity, - amount0Min: amount0Min, - amount1Min: amount1Min, - deadline: Math.floor(Date.now() / 1000) + 1800, - }) - - // console.log("amount 0", amount0) - // console.log("amount 1", amount1) + const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) + console.log("iswethtoken0", isWethToken0) const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 // Estimate proceeds from liquidating squeeth in LP - const ethAmountOutFromSwap = getSellQuote(wPowerPerpAmountInLPBefore) + const wPowerPerpAmountInLPBeforeVal = fromTokenAmount(wPowerPerpAmountInLPBefore, OSQUEETH_DECIMALS) + const ethAmountOutFromSwap = await getLimitEth(wPowerPerpAmountInLPBeforeVal) + console.log("ethAmountOutFromSwap", ethAmountOutFromSwap) - // Estimate of new LP with 0.01 weth safety margin - const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap) + // Estimate of new LP + const wethAmountToLP = new BigNumber(wethAmountInLPBefore).plus(ethAmountOutFromSwap).toFixed(0) + console.log("wPowerPerpAmountInLPBefore", wPowerPerpAmountInLPBefore.toString()) + console.log("wethAmountInLPBefore", wethAmountInLPBefore.toString()) + console.log("wethAmountToLP", wethAmountToLP) const abiCoder = new ethers.utils.AbiCoder() const rebalanceLpInVaultParams = [ { // Liquidate LP - rebalanceLpInVaultType: new BigNumber(1), // DecreaseLpLiquidity: + rebalanceLpInVaultType: new BigNumber(1).toFixed(0), // DecreaseLpLiquidity: // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min] data: abiCoder.encode( ['uint256', 'uint256', 'uint256', 'uint128', 'uint128'], [ - tokenId, - positionBefore.liquidity, - new BigNumber(100).multipliedBy(new BigNumber(10).pow(16)).toFixed(0), - new BigNumber(0).toFixed(0), - new BigNumber(0).toFixed(0), + uniTokenId, + position.liquidity, + fromTokenAmount(1, 18).toFixed(0), + 0, + 0, ], ), }, { // Sell all oSQTH for ETH - rebalanceLpInVaultType: new BigNumber(5), // GeneralSwap: + rebalanceLpInVaultType: new BigNumber(5).toFixed(0), // GeneralSwap: // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice] data: abiCoder.encode( ['address', 'address', 'uint256', 'uint256', 'uint24'], - [oSqueeth, weth, wPowerPerpAmountInLPBefore, new BigNumber(0).toFixed(0), 3000], + [oSqueeth, weth, wPowerPerpAmountInLPBefore, 0, 3000], ), }, { // Mint new LP - rebalanceLpInVaultType: new BigNumber(4).toString(), // MintNewLP + rebalanceLpInVaultType: new BigNumber(4).toFixed(0), // MintNewLP // lpWPowerPerpPool: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ] data: abiCoder.encode( ['address', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'], @@ -404,11 +400,11 @@ export const useRebalanceGeneralSwap = () => { controllerHelper, squeethPool, vaultId, - new BigNumber(0).toFixed(0), - new BigNumber(0).toFixed(0), + 0, + 0, wethAmountToLP, - amount0Min, - amount1Min, + amount0Min.toFixed(0), + amount1Min.toFixed(0), lowerTick, upperTick, ], @@ -416,10 +412,12 @@ export const useRebalanceGeneralSwap = () => { }, ] - await controllerContract.methods.updateOperator(vaultId, controllerHelper) + console.log("vaultId, collateralToFlashloan.toFixed(0)", vaultId, collateralToFlashloan.toFixed(0)) + console.log("rebalanceLpInVaultParams", rebalanceLpInVaultParams) + return handleTransaction( await controllerHelperContract.methods - .rebalanceLpInVault(vaultId, collateralToFlashloan, rebalanceLpInVaultParams) + .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) .send({ from: address, }), From 7b20c70aa1d0dde38ff73d46f1e3fc95d4fb1c57 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 5 Jul 2022 12:58:21 -0700 Subject: [PATCH 29/82] general swap updates --- packages/frontend/src/state/lp/hooks.ts | 119 +++++++++++++++++------- 1 file changed, 87 insertions(+), 32 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 4efce6fe5..90c40288a 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -2,14 +2,19 @@ import { FeeAmount, nearestUsableTick, TickMath, tickToPrice, TICK_SPACINGS } fr import { fromTokenAmount } from '@utils/calculations' import { useAtom, useAtomValue } from 'jotai' -import { addressesAtom, isWethToken0Atom } from '../positions/atoms' +import { addressesAtom, isWethToken0Atom, positionTypeAtom } from '../positions/atoms' import BigNumber from 'bignumber.js' import { BIG_ZERO, INDEX_SCALE, OSQUEETH_DECIMALS, UNI_POOL_FEES, WETH_DECIMALS } from '@constants/index' import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom, quoterContractAtom } from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' -import { addressAtom, web3Atom } from '../wallet/atoms' +import { addressAtom, signerAtom, web3Atom } from '../wallet/atoms' +import positionManagerAbi from '../../abis/NFTpositionmanager.json' +import controllerAbi from '../../abis/controller.json' import { normFactorAtom } from '../controller/atoms' import { Price, Token } from '@uniswap/sdk-core' + +// import { Price, Token, TickMath } from '@uniswap/v3-periphery' + import { useHandleTransaction } from '../wallet/hooks' import { squeethPriceeAtom, squeethTokenAtom, wethPriceAtom, wethTokenAtom } from '../squeethPool/atoms' import { ethers } from 'ethers' @@ -99,6 +104,7 @@ export const useOpenPositionDeposit = () => { const squeethPrice = await getTwapSqueethPrice() const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) console.log("squeethPrice", squeethPrice.toString()) + const ethDebt = await getDebtAmount(mintWSqueethAmount) // Do we want to hardcode a 150% collateralization ratio? console.log('squeeth price', squeethPrice.toString()) @@ -169,12 +175,12 @@ export const useCollectFees = () => { { rebalanceLpInVaultType: new BigNumber(6).toFixed(0), // CollectFees - data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [Number(uniTokenId), amount0Max, amount1Max]), + data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [uniTokenId, amount0Max, amount1Max]), }, { rebalanceLpInVaultType: new BigNumber(7).toFixed(0), // DepositExistingNftParams - data: abiCoder.encode(["uint256"], [Number(uniTokenId)]) + data: abiCoder.encode(["uint256"], [uniTokenId]) } ] @@ -332,37 +338,70 @@ export const useRebalanceGeneralSwap = () => { const getDecreaseLiquidity = useGetDecreaseLiquidity() const getPosition = useGetPosition() const getLimitEth = useGetLimitEth() + const getSqueethEquivalent = useGetSqueethEquivalent() const rebalanceGeneralSwap = useAppCallback( - async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { + async (vaultId: number, lowerTickInput: number, upperTickInput: number, newWethAmount: BigNumber, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) const uniTokenId = vaultBefore?.NFTCollateralId const position = await getPosition(uniTokenId) if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore) return - const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) - const debtInEth = await getDebtAmount(shortAmount) - const collateralToFlashloan = debtInEth.multipliedBy(1.5) + // const currentShortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + // console.log("currentShortAmount", currentShortAmount.toFixed(0)) + // const currentDebtInEth = await getDebtAmount(currentShortAmount) + // const collateralToFlashloan = currentDebtInEth.multipliedBy(1.5) + const amount0Min = new BigNumber(0) const amount1Min = new BigNumber(0) const lowerTick = nearestUsableTick(lowerTickInput, 3000) const upperTick = nearestUsableTick(upperTickInput, 3000) - // Get current LPpositions + + // Get current LP positions const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) - console.log("iswethtoken0", isWethToken0) + console.log("amount0", amount0) + console.log("amount1", amount1) + const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 + console.log("wPowerPerpAmountInLPBefore", wPowerPerpAmountInLPBefore) const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 + console.log("wethAmountInLPBefore", wethAmountInLPBefore) + + // Calculate difference with new amount of squeeth + const wethAmountToLP = fromTokenAmount(newWethAmount, OSQUEETH_DECIMALS) + console.log("wethAmountToLP", wethAmountToLP.toFixed(0)) + const needMoreWeth = new BigNumber(wethAmountInLPBefore).lt(new BigNumber(wethAmountToLP)) + console.log("needMoreWeth", needMoreWeth) + + const tokenIn = needMoreWeth ? oSqueeth : weth + const tokenOut = needMoreWeth ? weth : oSqueeth + + const amountIn = needMoreWeth ? await getSqueethEquivalent(new BigNumber(wethAmountToLP).minus(new BigNumber(wethAmountInLPBefore))) + : new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountToLP)).toFixed(0) + console.log("amountIn", amountIn) + + console.log("1st", [ + uniTokenId, + position.liquidity, + fromTokenAmount(1, 18).toFixed(0), + 0, + 0, + ]) + console.log("2nd", [tokenIn, tokenOut, amountIn, "0", 3000]) + console.log("3rd", [ + controllerHelper, + squeethPool, + vaultId, + "0", + "0", + wethAmountToLP.toFixed(0), + amount0Min.toFixed(0), + amount1Min.toFixed(0), + lowerTick, + upperTick, + ]) + // console.log("vaultId, collateralToFlashloan.toFixed(0)", vaultId, collateralToFlashloan.toFixed(0)) - // Estimate proceeds from liquidating squeeth in LP - const wPowerPerpAmountInLPBeforeVal = fromTokenAmount(wPowerPerpAmountInLPBefore, OSQUEETH_DECIMALS) - const ethAmountOutFromSwap = await getLimitEth(wPowerPerpAmountInLPBeforeVal) - console.log("ethAmountOutFromSwap", ethAmountOutFromSwap) - - // Estimate of new LP - const wethAmountToLP = new BigNumber(wethAmountInLPBefore).plus(ethAmountOutFromSwap).toFixed(0) - console.log("wPowerPerpAmountInLPBefore", wPowerPerpAmountInLPBefore.toString()) - console.log("wethAmountInLPBefore", wethAmountInLPBefore.toString()) - console.log("wethAmountToLP", wethAmountToLP) const abiCoder = new ethers.utils.AbiCoder() const rebalanceLpInVaultParams = [ @@ -387,7 +426,7 @@ export const useRebalanceGeneralSwap = () => { // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice] data: abiCoder.encode( ['address', 'address', 'uint256', 'uint256', 'uint24'], - [oSqueeth, weth, wPowerPerpAmountInLPBefore, 0, 3000], + [weth, oSqueeth, amountIn, 0, 3000], ), }, { @@ -402,7 +441,7 @@ export const useRebalanceGeneralSwap = () => { vaultId, 0, 0, - wethAmountToLP, + wethAmountToLP.toFixed(0), amount0Min.toFixed(0), amount1Min.toFixed(0), lowerTick, @@ -411,13 +450,9 @@ export const useRebalanceGeneralSwap = () => { ), }, ] - - console.log("vaultId, collateralToFlashloan.toFixed(0)", vaultId, collateralToFlashloan.toFixed(0)) - console.log("rebalanceLpInVaultParams", rebalanceLpInVaultParams) - return handleTransaction( await controllerHelperContract.methods - .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) + .rebalanceLpInVault(vaultId, fromTokenAmount(100, WETH_DECIMALS).toFixed(0), rebalanceLpInVaultParams) .send({ from: address, }), @@ -439,7 +474,6 @@ export const useGetPosition = () => { if (!contract) return null const position = await contract.methods.positions(uniTokenId).call() const { nonce, operator, token0, token1, fee, tickLower, tickUpper, liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128, tokensOwed0, tokensOwed1 } = position - console.log("unitokenid", uniTokenId) return { nonce, operator, @@ -525,10 +559,6 @@ export const useGetLimitEth = () => { const getLimitEth = useCallback( async (mintWSqueethAmount: BigNumber) => { - console.log("mintWsqueethAmount", mintWSqueethAmount.toFixed(0)) - console.log("osqueeth", oSqueeth) - console.log("weth", weth) - console.log("fee", 3000) if (!contract) return null const QuoteExactInputSingleParams = { @@ -548,6 +578,31 @@ export const useGetLimitEth = () => { return getLimitEth } +export const useGetSqueethEquivalent = () => { + const contract = useAtomValue(quoterContractAtom) + const {weth, oSqueeth} = useAtomValue(addressesAtom) + + const getSqueethEquivalent = useCallback( + async (wethAmount: BigNumber) => { + if (!contract) return null + + const QuoteExactInputSingleParams = { + tokenIn: weth, + tokenOut: oSqueeth, + amountIn: wethAmount.toFixed(0), + fee: 3000, + sqrtPriceLimitX96: 0 + } + + const limitEth = await contract.methods.quoteExactInputSingle(QuoteExactInputSingleParams).call() + return limitEth.amountOut + }, + [contract, weth, oSqueeth], + ) + + return getSqueethEquivalent +} + // export const getNow = async(provider: any) => { // const blockNumBefore = await provider.getBlockNumber(); // const blockBefore = await provider.getBlock(blockNumBefore); From 7e3ff900c43aa602e37599380f2ffdbd7e453e17 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 5 Jul 2022 15:46:09 -0700 Subject: [PATCH 30/82] latest genswap rebal --- packages/frontend/src/state/lp/hooks.ts | 160 ++++++++++++++++++++---- 1 file changed, 137 insertions(+), 23 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 90c40288a..d40c52870 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -1,4 +1,4 @@ -import { FeeAmount, nearestUsableTick, TickMath, tickToPrice, TICK_SPACINGS } from '@uniswap/v3-sdk' +import { FeeAmount, nearestUsableTick, SqrtPriceMath, TickMath, tickToPrice, TICK_SPACINGS } from '@uniswap/v3-sdk' import { fromTokenAmount } from '@utils/calculations' import { useAtom, useAtomValue } from 'jotai' @@ -102,10 +102,10 @@ export const useOpenPositionDeposit = () => { const openPositionDeposit = useAppCallback( async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, vaultID: number, onTxConfirmed?: () => void) => { const squeethPrice = await getTwapSqueethPrice() - const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) console.log("squeethPrice", squeethPrice.toString()) - + const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) const ethDebt = await getDebtAmount(mintWSqueethAmount) + // Do we want to hardcode a 150% collateralization ratio? console.log('squeeth price', squeethPrice.toString()) const collateralToMint = ethDebt.multipliedBy(3).div(2) @@ -203,6 +203,112 @@ export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: num return tickToPrice(baseToken, quoteToken, tick) } +// Rebalance via general swap +export const useRebalance = () => { + const address = useAtomValue(addressAtom) + const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) + const { controllerHelper, weth, oSqueeth, squeethPool } = useAtomValue(addressesAtom) + const controllerContract = useAtomValue(controllerContractAtom) + const handleTransaction = useHandleTransaction() + const isWethToken0 = useAtomValue(isWethToken0Atom) + const getDebtAmount = useGetDebtAmount() + const getVault = useGetVault() + const getDecreaseLiquidity = useGetDecreaseLiquidity() + const getPosition = useGetPosition() + const getLimitEth = useGetLimitEth() + const getSqueethEquivalent = useGetSqueethEquivalent() + const getTwapSqueethPrice = useGetTwapSqueethPrice() + const rebalance = useAppCallback( + async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { + const vaultBefore = await getVault(vaultId) + const uniTokenId = vaultBefore?.NFTCollateralId + const position = await getPosition(uniTokenId) + if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore) return + + const amount0Min = new BigNumber(0) + const amount1Min = new BigNumber(0) + + const lowerTick = nearestUsableTick(lowerTickInput, 3000) + const upperTick = nearestUsableTick(upperTickInput, 3000) + + const x96 = new BigNumber(2).pow(96) + const squeethPrice = new BigNumber(await getTwapSqueethPrice()) + const liquidity = new BigNumber(position.liquidity) + console.log(x96, "x96") + console.log("lowTick", lowerTick) + + // Calculate prices from ticks + const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(lowerTick).toString()).div(x96) + const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(upperTick).toString()).div(x96) + const sqrtSqueethPrice = new BigNumber(squeethPrice.sqrt()) + + // Calculate amounts of each asset to LP + // x = L(sqrt(upperPrice) - sqrt(squeethPrice))) / sqrt(squeethPrice) * sqrt(upperPrice) + // y = L(sqrt(squeethPrice) - sqrt(lowerPrice)) + const amount0 = liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div((sqrtSqueethPrice.times(sqrtUpperPrice))) + const amount1 = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) + + // const abiCoder = new ethers.utils.AbiCoder() + // const rebalanceLpInVaultParams = [ + // { + // // Liquidate LP + // rebalanceLpInVaultType: new BigNumber(1).toFixed(0), // DecreaseLpLiquidity: + // // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min] + // data: abiCoder.encode( + // ['uint256', 'uint256', 'uint256', 'uint128', 'uint128'], + // [ + // uniTokenId, + // position.liquidity, + // fromTokenAmount(1, 18).toFixed(0), + // 0, + // 0, + // ], + // ), + // }, + // { + // // Sell all oSQTH for ETH + // rebalanceLpInVaultType: new BigNumber(5).toFixed(0), // GeneralSwap: + // // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice] + // data: abiCoder.encode( + // ['address', 'address', 'uint256', 'uint256', 'uint24'], + // [weth, oSqueeth, amountIn, 0, 3000], + // ), + // }, + // { + // // Mint new LP + // rebalanceLpInVaultType: new BigNumber(4).toFixed(0), // MintNewLP + // // lpWPowerPerpPool: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ] + // data: abiCoder.encode( + // ['address', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'], + // [ + // controllerHelper, + // squeethPool, + // vaultId, + // 0, + // 0, + // wethAmountToLP.toFixed(0), + // amount0Min.toFixed(0), + // amount1Min.toFixed(0), + // lowerTick, + // upperTick, + // ], + // ), + // }, + // ] + // return handleTransaction( + // await controllerHelperContract.methods + // .rebalanceLpInVault(vaultId, fromTokenAmount(100, WETH_DECIMALS).toFixed(0), rebalanceLpInVaultParams) + // .send({ + // from: address, + // }), + // onTxConfirmed, + // ) + }, + [], + ) + return rebalance +} + // Rebalance via vault export const useRebalanceVault = () => { const address = useAtomValue(addressAtom) @@ -339,16 +445,13 @@ export const useRebalanceGeneralSwap = () => { const getPosition = useGetPosition() const getLimitEth = useGetLimitEth() const getSqueethEquivalent = useGetSqueethEquivalent() + const getTwapSqueethPrice = useGetTwapSqueethPrice() const rebalanceGeneralSwap = useAppCallback( - async (vaultId: number, lowerTickInput: number, upperTickInput: number, newWethAmount: BigNumber, onTxConfirmed?: () => void) => { + async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) const uniTokenId = vaultBefore?.NFTCollateralId const position = await getPosition(uniTokenId) if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore) return - // const currentShortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) - // console.log("currentShortAmount", currentShortAmount.toFixed(0)) - // const currentDebtInEth = await getDebtAmount(currentShortAmount) - // const collateralToFlashloan = currentDebtInEth.multipliedBy(1.5) const amount0Min = new BigNumber(0) const amount1Min = new BigNumber(0) @@ -359,25 +462,38 @@ export const useRebalanceGeneralSwap = () => { // Get current LP positions const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) - console.log("amount0", amount0) - console.log("amount1", amount1) - const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 console.log("wPowerPerpAmountInLPBefore", wPowerPerpAmountInLPBefore) const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 console.log("wethAmountInLPBefore", wethAmountInLPBefore) - // Calculate difference with new amount of squeeth - const wethAmountToLP = fromTokenAmount(newWethAmount, OSQUEETH_DECIMALS) - console.log("wethAmountToLP", wethAmountToLP.toFixed(0)) - const needMoreWeth = new BigNumber(wethAmountInLPBefore).lt(new BigNumber(wethAmountToLP)) + const x96 = new BigNumber(2).pow(96) + const squeethPrice = new BigNumber(await getTwapSqueethPrice()) + const liquidity = new BigNumber(position.liquidity) + + // Calculate prices from ticks + const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(lowerTick).toString()).div(x96) + const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(upperTick).toString()).div(x96) + const sqrtSqueethPrice = new BigNumber(squeethPrice.sqrt()) + + // Calculate amounts of each asset to LP + // x = L(sqrt(upperPrice) - sqrt(squeethPrice))) / sqrt(squeethPrice) * sqrt(upperPrice) + // y = L(sqrt(squeethPrice) - sqrt(lowerPrice)) + const newAmount0 = liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div((sqrtSqueethPrice.times(sqrtUpperPrice))) + const newAmount1 = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) + + // Calculate difference new position + const wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 + console.log("wethAmountInLPAfter", wethAmountInLPAfter) + console.log("wethAmountToLP", wethAmountInLPAfter.toFixed(0)) + const needMoreWeth = new BigNumber(wethAmountInLPBefore).lt(new BigNumber(wethAmountInLPAfter)) console.log("needMoreWeth", needMoreWeth) const tokenIn = needMoreWeth ? oSqueeth : weth const tokenOut = needMoreWeth ? weth : oSqueeth - const amountIn = needMoreWeth ? await getSqueethEquivalent(new BigNumber(wethAmountToLP).minus(new BigNumber(wethAmountInLPBefore))) - : new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountToLP)).toFixed(0) + const amountIn = needMoreWeth ? await getSqueethEquivalent(new BigNumber(wethAmountInLPAfter).minus(new BigNumber(wethAmountInLPBefore))) + : new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountInLPAfter)).toFixed(0) console.log("amountIn", amountIn) console.log("1st", [ @@ -394,14 +510,12 @@ export const useRebalanceGeneralSwap = () => { vaultId, "0", "0", - wethAmountToLP.toFixed(0), + wethAmountInLPAfter.toFixed(0), amount0Min.toFixed(0), amount1Min.toFixed(0), lowerTick, upperTick, ]) - // console.log("vaultId, collateralToFlashloan.toFixed(0)", vaultId, collateralToFlashloan.toFixed(0)) - const abiCoder = new ethers.utils.AbiCoder() const rebalanceLpInVaultParams = [ @@ -421,12 +535,12 @@ export const useRebalanceGeneralSwap = () => { ), }, { - // Sell all oSQTH for ETH + // Exchange necessary amount of oSQTH and ETH rebalanceLpInVaultType: new BigNumber(5).toFixed(0), // GeneralSwap: // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice] data: abiCoder.encode( ['address', 'address', 'uint256', 'uint256', 'uint24'], - [weth, oSqueeth, amountIn, 0, 3000], + [tokenIn, tokenOut, amountIn, 0, 3000], ), }, { @@ -441,7 +555,7 @@ export const useRebalanceGeneralSwap = () => { vaultId, 0, 0, - wethAmountToLP.toFixed(0), + wethAmountInLPAfter.toFixed(0), amount0Min.toFixed(0), amount1Min.toFixed(0), lowerTick, From bfb7d4f75914b5ddbc6b69a237168bb085911b5a Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 5 Jul 2022 15:51:19 -0700 Subject: [PATCH 31/82] buttons --- packages/frontend/pages/lp.tsx | 117 +++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index 70b959fb6..db7984519 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -15,9 +15,15 @@ import { SqueethTab, SqueethTabs } from '@components/Tabs' import { useETHPrice } from '@hooks/useETHPrice' import { supportedNetworkAtom } from 'src/state/wallet/atoms' import { useAtomValue } from 'jotai' -import { useOpenPositionDeposit } from 'src/state/lp/hooks' +import { useClosePosition, useOpenPositionDeposit, useRebalanceVault, useRebalanceGeneralSwap, useRebalance } from 'src/state/lp/hooks' +import { useCollectFees } from 'src/state/lp/hooks' import BigNumber from 'bignumber.js' import useAppCallback from '@hooks/useAppCallback' +import { useFirstValidVault } from 'src/state/positions/hooks' +import { useGetTwapSqueethPrice, useUpdateOperator } from 'src/state/controller/hooks' +import { addressesAtom } from 'src/state/positions/atoms' +import useAppEffect from '@hooks/useAppEffect' +import { CONTROLLER_HELPER } from '@constants/address' const useStyles = makeStyles((theme) => createStyles({ @@ -87,21 +93,68 @@ const useStyles = makeStyles((theme) => ) export function LPCalculator() { + const [isVaultApproved, setIsVaultApproved] = useState(true) const classes = useStyles() const { isRestricted } = useRestrictUser() const ethPrice = useETHPrice() const [lpType, setLpType] = useState(0) const supportedNetwork = useAtomValue(supportedNetworkAtom) + const squeethPrice = useGetTwapSqueethPrice() const openLPPosition = useOpenPositionDeposit() + const closeLPPosition = useClosePosition() + const collectFees = useCollectFees() + const rebalanceVault = useRebalanceVault() + const rebalanceSwap = useRebalanceGeneralSwap() + const rebalance = useRebalance() + const { vaultId, validVault: vault } = useFirstValidVault() const openPos = useAppCallback(async () => { try { - await openLPPosition(new BigNumber(50), -887220, 887220, () => {}) + await openLPPosition(new BigNumber(50), -887220, 887220, 0, () => {}) } catch (e) { console.log(e) } - }, []) + }, [vaultId, squeethPrice]) + const collFees = useAppCallback(async () => { + try { + await collectFees(Number(682), () => {}) + } catch (e) { + console.log(e) + } + }, [vaultId]) + + const closePos = useAppCallback(async () => { + try { + await closeLPPosition(Number(682), () => {}) + } catch (e) { + console.log(e) + } + }, [vaultId]) + + const rebalVault = useAppCallback(async () => { + try { + await rebalanceVault(Number(682), -887220, 887220, () => {}) + } catch (e) { + console.log(e) + } + }, [vaultId]) + + const rebalSwap = useAppCallback(async () => { + try { + await rebalanceSwap(Number(682), -887220, 887220, () => {}) + } catch (e) { + console.log(e) + } + }, [vaultId]) + + const rebal = useAppCallback(async () => { + try { + await rebalance(Number(682), -887220, 887220, () => {}) + } catch (e) { + console.log(e) + } + }, [vaultId]) return (
@@ -188,6 +241,62 @@ export function LPCalculator() { > {'Open Mint and Deposit LP Position'} + + + + + + + + + + +
) : (
@@ -247,4 +356,4 @@ export function LPage() { ) } -export default LPage +export default LPage \ No newline at end of file From 1180d146b90d4c8bd5a55fe3f911ca57cfab469c Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 5 Jul 2022 16:45:40 -0700 Subject: [PATCH 32/82] general swap rebalance works --- packages/frontend/src/state/lp/hooks.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index d40c52870..6a4ff8211 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -452,6 +452,9 @@ export const useRebalanceGeneralSwap = () => { const uniTokenId = vaultBefore?.NFTCollateralId const position = await getPosition(uniTokenId) if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore) return + const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + const debtInEth = await getDebtAmount(shortAmount) + const collateralToFlashloan = debtInEth.multipliedBy(1.5) const amount0Min = new BigNumber(0) const amount1Min = new BigNumber(0) @@ -484,7 +487,9 @@ export const useRebalanceGeneralSwap = () => { // Calculate difference new position const wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 - console.log("wethAmountInLPAfter", wethAmountInLPAfter) + console.log("wethAmountInLPAfter", wethAmountInLPAfter.toFixed(0)) + const wPowerPerpAmountInLPAfter = isWethToken0 ? newAmount1 : newAmount0 + console.log("wPowerPerpAmountInLPAfter", wPowerPerpAmountInLPAfter.toFixed(0)) console.log("wethAmountToLP", wethAmountInLPAfter.toFixed(0)) const needMoreWeth = new BigNumber(wethAmountInLPBefore).lt(new BigNumber(wethAmountInLPAfter)) console.log("needMoreWeth", needMoreWeth) @@ -553,7 +558,7 @@ export const useRebalanceGeneralSwap = () => { controllerHelper, squeethPool, vaultId, - 0, + wPowerPerpAmountInLPAfter.toFixed(0), 0, wethAmountInLPAfter.toFixed(0), amount0Min.toFixed(0), @@ -566,7 +571,7 @@ export const useRebalanceGeneralSwap = () => { ] return handleTransaction( await controllerHelperContract.methods - .rebalanceLpInVault(vaultId, fromTokenAmount(100, WETH_DECIMALS).toFixed(0), rebalanceLpInVaultParams) + .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) .send({ from: address, }), From c5c118c19376634e460b289490a5aa59e3a96ce3 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 5 Jul 2022 17:25:48 -0700 Subject: [PATCH 33/82] delete rebalance test --- packages/frontend/src/state/lp/hooks.ts | 107 +----------------------- 1 file changed, 1 insertion(+), 106 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 6a4ff8211..58d2aaae5 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -203,112 +203,6 @@ export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: num return tickToPrice(baseToken, quoteToken, tick) } -// Rebalance via general swap -export const useRebalance = () => { - const address = useAtomValue(addressAtom) - const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) - const { controllerHelper, weth, oSqueeth, squeethPool } = useAtomValue(addressesAtom) - const controllerContract = useAtomValue(controllerContractAtom) - const handleTransaction = useHandleTransaction() - const isWethToken0 = useAtomValue(isWethToken0Atom) - const getDebtAmount = useGetDebtAmount() - const getVault = useGetVault() - const getDecreaseLiquidity = useGetDecreaseLiquidity() - const getPosition = useGetPosition() - const getLimitEth = useGetLimitEth() - const getSqueethEquivalent = useGetSqueethEquivalent() - const getTwapSqueethPrice = useGetTwapSqueethPrice() - const rebalance = useAppCallback( - async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { - const vaultBefore = await getVault(vaultId) - const uniTokenId = vaultBefore?.NFTCollateralId - const position = await getPosition(uniTokenId) - if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore) return - - const amount0Min = new BigNumber(0) - const amount1Min = new BigNumber(0) - - const lowerTick = nearestUsableTick(lowerTickInput, 3000) - const upperTick = nearestUsableTick(upperTickInput, 3000) - - const x96 = new BigNumber(2).pow(96) - const squeethPrice = new BigNumber(await getTwapSqueethPrice()) - const liquidity = new BigNumber(position.liquidity) - console.log(x96, "x96") - console.log("lowTick", lowerTick) - - // Calculate prices from ticks - const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(lowerTick).toString()).div(x96) - const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(upperTick).toString()).div(x96) - const sqrtSqueethPrice = new BigNumber(squeethPrice.sqrt()) - - // Calculate amounts of each asset to LP - // x = L(sqrt(upperPrice) - sqrt(squeethPrice))) / sqrt(squeethPrice) * sqrt(upperPrice) - // y = L(sqrt(squeethPrice) - sqrt(lowerPrice)) - const amount0 = liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div((sqrtSqueethPrice.times(sqrtUpperPrice))) - const amount1 = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) - - // const abiCoder = new ethers.utils.AbiCoder() - // const rebalanceLpInVaultParams = [ - // { - // // Liquidate LP - // rebalanceLpInVaultType: new BigNumber(1).toFixed(0), // DecreaseLpLiquidity: - // // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min] - // data: abiCoder.encode( - // ['uint256', 'uint256', 'uint256', 'uint128', 'uint128'], - // [ - // uniTokenId, - // position.liquidity, - // fromTokenAmount(1, 18).toFixed(0), - // 0, - // 0, - // ], - // ), - // }, - // { - // // Sell all oSQTH for ETH - // rebalanceLpInVaultType: new BigNumber(5).toFixed(0), // GeneralSwap: - // // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice] - // data: abiCoder.encode( - // ['address', 'address', 'uint256', 'uint256', 'uint24'], - // [weth, oSqueeth, amountIn, 0, 3000], - // ), - // }, - // { - // // Mint new LP - // rebalanceLpInVaultType: new BigNumber(4).toFixed(0), // MintNewLP - // // lpWPowerPerpPool: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ] - // data: abiCoder.encode( - // ['address', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'], - // [ - // controllerHelper, - // squeethPool, - // vaultId, - // 0, - // 0, - // wethAmountToLP.toFixed(0), - // amount0Min.toFixed(0), - // amount1Min.toFixed(0), - // lowerTick, - // upperTick, - // ], - // ), - // }, - // ] - // return handleTransaction( - // await controllerHelperContract.methods - // .rebalanceLpInVault(vaultId, fromTokenAmount(100, WETH_DECIMALS).toFixed(0), rebalanceLpInVaultParams) - // .send({ - // from: address, - // }), - // onTxConfirmed, - // ) - }, - [], - ) - return rebalance -} - // Rebalance via vault export const useRebalanceVault = () => { const address = useAtomValue(addressAtom) @@ -478,6 +372,7 @@ export const useRebalanceGeneralSwap = () => { const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(lowerTick).toString()).div(x96) const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(upperTick).toString()).div(x96) const sqrtSqueethPrice = new BigNumber(squeethPrice.sqrt()) + console.log("sqrtSqueethPrice", sqrtSqueethPrice.toFixed(0)) // Calculate amounts of each asset to LP // x = L(sqrt(upperPrice) - sqrt(squeethPrice))) / sqrt(squeethPrice) * sqrt(upperPrice) From ea83cc7d6b58697b5a2591a6092a6e800783df50 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 5 Jul 2022 18:50:49 -0700 Subject: [PATCH 34/82] debugging swap rebal needmoreweth --- packages/frontend/pages/lp.tsx | 23 +------- packages/frontend/src/state/lp/hooks.ts | 74 ++++++++++++++++++------- 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index db7984519..eaa48dc77 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -15,7 +15,7 @@ import { SqueethTab, SqueethTabs } from '@components/Tabs' import { useETHPrice } from '@hooks/useETHPrice' import { supportedNetworkAtom } from 'src/state/wallet/atoms' import { useAtomValue } from 'jotai' -import { useClosePosition, useOpenPositionDeposit, useRebalanceVault, useRebalanceGeneralSwap, useRebalance } from 'src/state/lp/hooks' +import { useClosePosition, useOpenPositionDeposit, useRebalanceVault, useRebalanceGeneralSwap } from 'src/state/lp/hooks' import { useCollectFees } from 'src/state/lp/hooks' import BigNumber from 'bignumber.js' import useAppCallback from '@hooks/useAppCallback' @@ -105,7 +105,6 @@ export function LPCalculator() { const collectFees = useCollectFees() const rebalanceVault = useRebalanceVault() const rebalanceSwap = useRebalanceGeneralSwap() - const rebalance = useRebalance() const { vaultId, validVault: vault } = useFirstValidVault() const openPos = useAppCallback(async () => { @@ -142,19 +141,12 @@ export function LPCalculator() { const rebalSwap = useAppCallback(async () => { try { - await rebalanceSwap(Number(682), -887220, 887220, () => {}) + await rebalanceSwap(Number(682), 0, 3000, () => {}) } catch (e) { console.log(e) } }, [vaultId]) - const rebal = useAppCallback(async () => { - try { - await rebalance(Number(682), -887220, 887220, () => {}) - } catch (e) { - console.log(e) - } - }, [vaultId]) return (
@@ -286,17 +278,6 @@ export function LPCalculator() { {'Rebalance General Swap'} - -
) : (
diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 58d2aaae5..1804a0fd5 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -5,13 +5,14 @@ import { useAtom, useAtomValue } from 'jotai' import { addressesAtom, isWethToken0Atom, positionTypeAtom } from '../positions/atoms' import BigNumber from 'bignumber.js' import { BIG_ZERO, INDEX_SCALE, OSQUEETH_DECIMALS, UNI_POOL_FEES, WETH_DECIMALS } from '@constants/index' -import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom, quoterContractAtom } from '../contracts/atoms' +import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom, quoterContractAtom, squeethPoolContractAtom } from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' import { addressAtom, signerAtom, web3Atom } from '../wallet/atoms' import positionManagerAbi from '../../abis/NFTpositionmanager.json' import controllerAbi from '../../abis/controller.json' import { normFactorAtom } from '../controller/atoms' import { Price, Token } from '@uniswap/sdk-core' +import { Contract } from 'web3-eth-contract' // import { Price, Token, TickMath } from '@uniswap/v3-periphery' @@ -340,12 +341,13 @@ export const useRebalanceGeneralSwap = () => { const getLimitEth = useGetLimitEth() const getSqueethEquivalent = useGetSqueethEquivalent() const getTwapSqueethPrice = useGetTwapSqueethPrice() + const squeethPoolContract = useAtomValue(squeethPoolContractAtom) const rebalanceGeneralSwap = useAppCallback( async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) const uniTokenId = vaultBefore?.NFTCollateralId const position = await getPosition(uniTokenId) - if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore) return + if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore || !squeethPoolContract) return const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) const debtInEth = await getDebtAmount(shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(1.5) @@ -355,6 +357,8 @@ export const useRebalanceGeneralSwap = () => { const lowerTick = nearestUsableTick(lowerTickInput, 3000) const upperTick = nearestUsableTick(upperTickInput, 3000) + console.log("lowerTick", lowerTick) + console.log("uppertick", upperTick) // Get current LP positions const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) @@ -371,28 +375,46 @@ export const useRebalanceGeneralSwap = () => { // Calculate prices from ticks const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(lowerTick).toString()).div(x96) const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(upperTick).toString()).div(x96) - const sqrtSqueethPrice = new BigNumber(squeethPrice.sqrt()) - console.log("sqrtSqueethPrice", sqrtSqueethPrice.toFixed(0)) - - // Calculate amounts of each asset to LP - // x = L(sqrt(upperPrice) - sqrt(squeethPrice))) / sqrt(squeethPrice) * sqrt(upperPrice) - // y = L(sqrt(squeethPrice) - sqrt(lowerPrice)) - const newAmount0 = liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div((sqrtSqueethPrice.times(sqrtUpperPrice))) - const newAmount1 = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) + const { sqrtPriceX96 } = await getPoolState(squeethPoolContract) + const sqrtSqueethPrice = new BigNumber(sqrtPriceX96.toString()).div(x96) + console.log("sqrtSqueethPrice", sqrtSqueethPrice.toString()) + + // Walls + const upperDifference = sqrtUpperPrice.minus(sqrtSqueethPrice) + const lowerDifference = sqrtSqueethPrice.minus(sqrtLowerPrice) + + let newAmount0 + let newAmount1 + if (sqrtUpperPrice.lt(sqrtSqueethPrice)) { + console.log("case 1") + newAmount0 = 0 + newAmount1 = (liquidity.times(sqrtUpperPrice)).minus(liquidity.times(sqrtLowerPrice)) + } else if (sqrtSqueethPrice.lt(sqrtLowerPrice)) { + console.log("case 2") + newAmount0 = (liquidity.div(sqrtLowerPrice)).minus(liquidity.div(sqrtUpperPrice)) + newAmount1 = 0 + } else { + console.log("case 3") + // Calculate amounts of each asset to LP + // x = L(sqrt(upperPrice) - sqrt(squeethPrice))) / sqrt(squeethPrice) * sqrt(upperPrice) + // y = L(sqrt(squeethPrice) - sqrt(lowerPrice)) + newAmount0 = liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div((sqrtSqueethPrice.times(sqrtUpperPrice))) + newAmount1 = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) + } // Calculate difference new position const wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 console.log("wethAmountInLPAfter", wethAmountInLPAfter.toFixed(0)) const wPowerPerpAmountInLPAfter = isWethToken0 ? newAmount1 : newAmount0 console.log("wPowerPerpAmountInLPAfter", wPowerPerpAmountInLPAfter.toFixed(0)) - console.log("wethAmountToLP", wethAmountInLPAfter.toFixed(0)) + console.log("wethAmountInLPAfter", wethAmountInLPAfter.toFixed(0)) const needMoreWeth = new BigNumber(wethAmountInLPBefore).lt(new BigNumber(wethAmountInLPAfter)) console.log("needMoreWeth", needMoreWeth) const tokenIn = needMoreWeth ? oSqueeth : weth const tokenOut = needMoreWeth ? weth : oSqueeth - const amountIn = needMoreWeth ? await getSqueethEquivalent(new BigNumber(wethAmountInLPAfter).minus(new BigNumber(wethAmountInLPBefore))) + const amountIn = needMoreWeth ? new BigNumber(wPowerPerpAmountInLPAfter).minus(new BigNumber(wPowerPerpAmountInLPBefore)).toFixed(0) : new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountInLPAfter)).toFixed(0) console.log("amountIn", amountIn) @@ -408,8 +430,8 @@ export const useRebalanceGeneralSwap = () => { controllerHelper, squeethPool, vaultId, - "0", - "0", + wPowerPerpAmountInLPAfter.toFixed(0), + 0, wethAmountInLPAfter.toFixed(0), amount0Min.toFixed(0), amount1Min.toFixed(0), @@ -617,8 +639,22 @@ export const useGetSqueethEquivalent = () => { return getSqueethEquivalent } -// export const getNow = async(provider: any) => { -// const blockNumBefore = await provider.getBlockNumber(); -// const blockBefore = await provider.getBlock(blockNumBefore); -// return blockBefore.timestamp; -// } +async function getPoolState(squeethContract: Contract) { + const [slot, liquidity] = await Promise.all([ + squeethContract?.methods.slot0().call(), + squeethContract?.methods.liquidity().call(), + ]) + + const PoolState = { + liquidity, + sqrtPriceX96: slot[0], + tick: slot[1], + observationIndex: slot[2], + observationCardinality: slot[3], + observationCardinalityNext: slot[4], + feeProtocol: slot[5], + unlocked: slot[6], + } + + return PoolState +} \ No newline at end of file From a49af15aa5f3096fc2db0836222892ed9306c659 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 5 Jul 2022 19:14:04 -0700 Subject: [PATCH 35/82] walls --- packages/frontend/src/state/lp/hooks.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 1804a0fd5..bf32fa0b1 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -379,10 +379,6 @@ export const useRebalanceGeneralSwap = () => { const sqrtSqueethPrice = new BigNumber(sqrtPriceX96.toString()).div(x96) console.log("sqrtSqueethPrice", sqrtSqueethPrice.toString()) - // Walls - const upperDifference = sqrtUpperPrice.minus(sqrtSqueethPrice) - const lowerDifference = sqrtSqueethPrice.minus(sqrtLowerPrice) - let newAmount0 let newAmount1 if (sqrtUpperPrice.lt(sqrtSqueethPrice)) { @@ -414,8 +410,8 @@ export const useRebalanceGeneralSwap = () => { const tokenIn = needMoreWeth ? oSqueeth : weth const tokenOut = needMoreWeth ? weth : oSqueeth - const amountIn = needMoreWeth ? new BigNumber(wPowerPerpAmountInLPAfter).minus(new BigNumber(wPowerPerpAmountInLPBefore)).toFixed(0) - : new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountInLPAfter)).toFixed(0) + const amountIn = needMoreWeth ? new BigNumber(wPowerPerpAmountInLPAfter).minus(new BigNumber(wPowerPerpAmountInLPBefore)).absoluteValue().toFixed(0) + : new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountInLPAfter)).absoluteValue().toFixed(0) console.log("amountIn", amountIn) console.log("1st", [ From e5d35aff93d157da6987a6cf722dfc39123186c2 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 7 Jul 2022 13:41:16 -0700 Subject: [PATCH 36/82] add onchange params --- packages/frontend/src/state/lp/hooks.ts | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index bf32fa0b1..d15db8134 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -88,7 +88,7 @@ export const useClosePosition = () => { }), onTxConfirmed, ) - }, [address, controllerHelperContract, controllerContract]) + }, [address, controllerHelperContract, controllerContract, handleTransaction, getDebtAmount, getVault, getPosition, getLimitEth]) return closePosition } @@ -140,7 +140,7 @@ export const useOpenPositionDeposit = () => { onTxConfirmed, ) }, - [address, squeethPool, contract], + [address, squeethPool, contract, handleTransaction, getTwapSqueethPrice, getDebtAmount], ) return openPositionDeposit } @@ -193,17 +193,10 @@ export const useCollectFees = () => { }), onTxConfirmed, ) - }, []) + }, [address, controllerHelperContract, controllerContract, handleTransaction, getDebtAmount, getVault]) return collectFees } -export function getTickToPrice(baseToken?: Token, quoteToken?: Token, tick?: number): Price | undefined { - if (!baseToken || !quoteToken || typeof tick !== 'number') { - return undefined - } - return tickToPrice(baseToken, quoteToken, tick) -} - // Rebalance via vault export const useRebalanceVault = () => { const address = useAtomValue(addressAtom) @@ -338,8 +331,6 @@ export const useRebalanceGeneralSwap = () => { const getVault = useGetVault() const getDecreaseLiquidity = useGetDecreaseLiquidity() const getPosition = useGetPosition() - const getLimitEth = useGetLimitEth() - const getSqueethEquivalent = useGetSqueethEquivalent() const getTwapSqueethPrice = useGetTwapSqueethPrice() const squeethPoolContract = useAtomValue(squeethPoolContractAtom) const rebalanceGeneralSwap = useAppCallback( @@ -491,7 +482,7 @@ export const useRebalanceGeneralSwap = () => { onTxConfirmed, ) }, - [], + [address, controllerHelperContract, controllerHelper, weth, oSqueeth, squeethPool, controllerContract, handleTransaction, isWethToken0, getDebtAmount, getVault, getDecreaseLiquidity, getPosition, getTwapSqueethPrice, squeethPoolContract], ) return rebalanceGeneralSwap } From dd209f64e47a1eb5c9968e5f94fbf3d0b8066dd7 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Fri, 8 Jul 2022 17:37:01 -0700 Subject: [PATCH 37/82] separate cases --- packages/frontend/pages/lp.tsx | 4 +-- packages/frontend/src/state/lp/hooks.ts | 39 ++++++++++++++++--------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index eaa48dc77..b4cf14a97 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -137,11 +137,11 @@ export function LPCalculator() { } catch (e) { console.log(e) } - }, [vaultId]) +}, [vaultId]) const rebalSwap = useAppCallback(async () => { try { - await rebalanceSwap(Number(682), 0, 3000, () => {}) + await rebalanceSwap(Number(682), -100000, -80000, () => {}) } catch (e) { console.log(e) } diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index d15db8134..603caae6b 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -354,13 +354,13 @@ export const useRebalanceGeneralSwap = () => { // Get current LP positions const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) + console.log("iswethtoken0", isWethToken0) const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 console.log("wPowerPerpAmountInLPBefore", wPowerPerpAmountInLPBefore) const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 console.log("wethAmountInLPBefore", wethAmountInLPBefore) const x96 = new BigNumber(2).pow(96) - const squeethPrice = new BigNumber(await getTwapSqueethPrice()) const liquidity = new BigNumber(position.liquidity) // Calculate prices from ticks @@ -368,41 +368,52 @@ export const useRebalanceGeneralSwap = () => { const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(upperTick).toString()).div(x96) const { sqrtPriceX96 } = await getPoolState(squeethPoolContract) const sqrtSqueethPrice = new BigNumber(sqrtPriceX96.toString()).div(x96) + console.log("sqrtLowerPrice", sqrtLowerPrice.toString()) + console.log("sqrtUpperPrice", sqrtUpperPrice.toString()) console.log("sqrtSqueethPrice", sqrtSqueethPrice.toString()) - let newAmount0 - let newAmount1 + let newAmount0, newAmount1, amountIn, wethAmountInLPAfter, wPowerPerpAmountInLPAfter, needMoreWeth, tokenIn, tokenOut if (sqrtUpperPrice.lt(sqrtSqueethPrice)) { console.log("case 1") + // All weth position newAmount0 = 0 newAmount1 = (liquidity.times(sqrtUpperPrice)).minus(liquidity.times(sqrtLowerPrice)) + wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 + wPowerPerpAmountInLPAfter = isWethToken0 ? newAmount1 : newAmount0 + amountIn = new BigNumber(wPowerPerpAmountInLPBefore).minus(new BigNumber(wPowerPerpAmountInLPAfter)).toFixed(0) + tokenIn = oSqueeth + tokenOut = weth } else if (sqrtSqueethPrice.lt(sqrtLowerPrice)) { console.log("case 2") + // All squeeth position newAmount0 = (liquidity.div(sqrtLowerPrice)).minus(liquidity.div(sqrtUpperPrice)) newAmount1 = 0 + wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 + wPowerPerpAmountInLPAfter = isWethToken0 ? newAmount1 : newAmount0 + amountIn = wethAmountInLPBefore + tokenIn = weth + tokenOut = oSqueeth } else { console.log("case 3") // Calculate amounts of each asset to LP // x = L(sqrt(upperPrice) - sqrt(squeethPrice))) / sqrt(squeethPrice) * sqrt(upperPrice) // y = L(sqrt(squeethPrice) - sqrt(lowerPrice)) + // Calculate difference new position newAmount0 = liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div((sqrtSqueethPrice.times(sqrtUpperPrice))) newAmount1 = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) + wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 + wPowerPerpAmountInLPAfter = isWethToken0 ? newAmount1 : newAmount0 + needMoreWeth = new BigNumber(wethAmountInLPBefore).lt(new BigNumber(wethAmountInLPAfter)) + tokenIn = needMoreWeth ? oSqueeth : weth + tokenOut = needMoreWeth ? weth : oSqueeth + amountIn = amountIn = needMoreWeth ? new BigNumber(wPowerPerpAmountInLPAfter).minus(new BigNumber(wPowerPerpAmountInLPBefore)).toFixed(0) + : new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountInLPAfter)).toFixed(0) } - - // Calculate difference new position - const wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 console.log("wethAmountInLPAfter", wethAmountInLPAfter.toFixed(0)) - const wPowerPerpAmountInLPAfter = isWethToken0 ? newAmount1 : newAmount0 console.log("wPowerPerpAmountInLPAfter", wPowerPerpAmountInLPAfter.toFixed(0)) console.log("wethAmountInLPAfter", wethAmountInLPAfter.toFixed(0)) - const needMoreWeth = new BigNumber(wethAmountInLPBefore).lt(new BigNumber(wethAmountInLPAfter)) console.log("needMoreWeth", needMoreWeth) - - const tokenIn = needMoreWeth ? oSqueeth : weth - const tokenOut = needMoreWeth ? weth : oSqueeth - - const amountIn = needMoreWeth ? new BigNumber(wPowerPerpAmountInLPAfter).minus(new BigNumber(wPowerPerpAmountInLPBefore)).absoluteValue().toFixed(0) - : new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountInLPAfter)).absoluteValue().toFixed(0) + console.log("liquidity", liquidity.toString()) console.log("amountIn", amountIn) console.log("1st", [ From c3cc0262b9777142a3e2e1a6522744da54a3d6e5 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Fri, 8 Jul 2022 18:27:27 -0700 Subject: [PATCH 38/82] fixed one-sided LP positions --- packages/frontend/pages/lp.tsx | 2 +- packages/frontend/src/state/lp/hooks.ts | 45 ++++++++++++------------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index b4cf14a97..b05a7e8be 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -141,7 +141,7 @@ export function LPCalculator() { const rebalSwap = useAppCallback(async () => { try { - await rebalanceSwap(Number(682), -100000, -80000, () => {}) + await rebalanceSwap(Number(682), 0, 80000, () => {}) } catch (e) { console.log(e) } diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 603caae6b..025aa4cf6 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -44,7 +44,7 @@ export const useClosePosition = () => { const getDebtAmount = useGetDebtAmount() const getVault = useGetVault() const getPosition = useGetPosition() - const getLimitEth = useGetLimitEth() + const getQuote = useGetQuote() const closePosition = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) const uniTokenId = vaultBefore?.NFTCollateralId @@ -63,7 +63,7 @@ export const useClosePosition = () => { const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) const debtInEth = await getDebtAmount(shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(1.5) - const limitEth = await getLimitEth(shortAmount) + const limitEth = await getQuote(shortAmount, true) const flashloanCloseVaultLpNftParam = { vaultId: vaultId, @@ -88,7 +88,7 @@ export const useClosePosition = () => { }), onTxConfirmed, ) - }, [address, controllerHelperContract, controllerContract, handleTransaction, getDebtAmount, getVault, getPosition, getLimitEth]) + }, [address, controllerHelperContract, controllerContract, handleTransaction, getDebtAmount, getVault, getPosition, getQuote]) return closePosition } @@ -213,7 +213,7 @@ export const useRebalanceVault = () => { const getTotalSupply = useGetTotalSupply() const getTokenByIndex = useGetTokenByIndex() const getDecreaseLiquidity = useGetDecreaseLiquidity() - const getLimitEth = useGetLimitEth() + const getQuote = useGetQuote() const rebalanceVault = useAppCallback( async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) @@ -240,7 +240,7 @@ export const useRebalanceVault = () => { // Estimate proceeds from liquidating squeeth in LP const wPowerPerpAmountInLPBeforeVal = fromTokenAmount(wPowerPerpAmountInLPBefore, OSQUEETH_DECIMALS) - const ethAmountOutFromSwap = await getLimitEth(wPowerPerpAmountInLPBeforeVal) + const ethAmountOutFromSwap = await getQuote(wPowerPerpAmountInLPBeforeVal, true) console.log("ethAmountOutFromSwap", ethAmountOutFromSwap) // Estimate of new LP @@ -333,6 +333,7 @@ export const useRebalanceGeneralSwap = () => { const getPosition = useGetPosition() const getTwapSqueethPrice = useGetTwapSqueethPrice() const squeethPoolContract = useAtomValue(squeethPoolContractAtom) + const getQuote = useGetQuote() const rebalanceGeneralSwap = useAppCallback( async (vaultId: number, lowerTickInput: number, upperTickInput: number, onTxConfirmed?: () => void) => { const vaultBefore = await getVault(vaultId) @@ -376,20 +377,18 @@ export const useRebalanceGeneralSwap = () => { if (sqrtUpperPrice.lt(sqrtSqueethPrice)) { console.log("case 1") // All weth position - newAmount0 = 0 - newAmount1 = (liquidity.times(sqrtUpperPrice)).minus(liquidity.times(sqrtLowerPrice)) - wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 - wPowerPerpAmountInLPAfter = isWethToken0 ? newAmount1 : newAmount0 - amountIn = new BigNumber(wPowerPerpAmountInLPBefore).minus(new BigNumber(wPowerPerpAmountInLPAfter)).toFixed(0) + wPowerPerpAmountInLPAfter = 0 + const ethAmountOut = await getQuote(new BigNumber(wPowerPerpAmountInLPBefore), true) + wethAmountInLPAfter = new BigNumber(ethAmountOut).plus(wethAmountInLPBefore) + amountIn = wPowerPerpAmountInLPBefore tokenIn = oSqueeth tokenOut = weth } else if (sqrtSqueethPrice.lt(sqrtLowerPrice)) { console.log("case 2") // All squeeth position - newAmount0 = (liquidity.div(sqrtLowerPrice)).minus(liquidity.div(sqrtUpperPrice)) - newAmount1 = 0 - wethAmountInLPAfter = isWethToken0 ? newAmount0 : newAmount1 - wPowerPerpAmountInLPAfter = isWethToken0 ? newAmount1 : newAmount0 + wethAmountInLPAfter = 0 + const squeethAmountOut = await getQuote(new BigNumber(wethAmountInLPBefore), false) + wPowerPerpAmountInLPAfter = new BigNumber(squeethAmountOut).plus(wPowerPerpAmountInLPBefore) amountIn = wethAmountInLPBefore tokenIn = weth tokenOut = oSqueeth @@ -587,29 +586,29 @@ export const useGetDecreaseLiquidity = () => { } -export const useGetLimitEth = () => { +export const useGetQuote = () => { const contract = useAtomValue(quoterContractAtom) const {weth, oSqueeth} = useAtomValue(addressesAtom) - const getLimitEth = useCallback( - async (mintWSqueethAmount: BigNumber) => { + const getQuote = useCallback( + async (amount: BigNumber, squeethIn: boolean) => { if (!contract) return null const QuoteExactInputSingleParams = { - tokenIn: oSqueeth, - tokenOut: weth, - amountIn: mintWSqueethAmount.toFixed(0), + tokenIn: squeethIn ? oSqueeth : weth, + tokenOut: squeethIn ? weth : oSqueeth, + amountIn: amount.toFixed(0), fee: 3000, sqrtPriceLimitX96: 0 } - const limitEth = await contract.methods.quoteExactInputSingle(QuoteExactInputSingleParams).call() - return limitEth.amountOut + const quote = await contract.methods.quoteExactInputSingle(QuoteExactInputSingleParams).call() + return quote.amountOut }, [contract, weth, oSqueeth], ) - return getLimitEth + return getQuote } export const useGetSqueethEquivalent = () => { From a453ea94d5f3e651df76e18bd0e77dff81348159 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 12 Jul 2022 14:44:08 -0700 Subject: [PATCH 39/82] change rebalance to real amounts from virtual amounts --- packages/frontend/pages/lp.tsx | 37 ++- packages/frontend/src/constants/address.ts | 7 + packages/frontend/src/state/lp/hooks.ts | 245 ++---------------- .../frontend/src/state/positions/atoms.ts | 2 + .../hardhat/test/e2e/periphery/fe-testing.ts | 238 +++++++++++++++++ 5 files changed, 288 insertions(+), 241 deletions(-) create mode 100644 packages/hardhat/test/e2e/periphery/fe-testing.ts diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index b05a7e8be..925824226 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -15,15 +15,13 @@ import { SqueethTab, SqueethTabs } from '@components/Tabs' import { useETHPrice } from '@hooks/useETHPrice' import { supportedNetworkAtom } from 'src/state/wallet/atoms' import { useAtomValue } from 'jotai' -import { useClosePosition, useOpenPositionDeposit, useRebalanceVault, useRebalanceGeneralSwap } from 'src/state/lp/hooks' +import { useClosePosition, useOpenPositionDeposit, useRebalanceGeneralSwap } from 'src/state/lp/hooks' import { useCollectFees } from 'src/state/lp/hooks' import BigNumber from 'bignumber.js' import useAppCallback from '@hooks/useAppCallback' import { useFirstValidVault } from 'src/state/positions/hooks' import { useGetTwapSqueethPrice, useUpdateOperator } from 'src/state/controller/hooks' import { addressesAtom } from 'src/state/positions/atoms' -import useAppEffect from '@hooks/useAppEffect' -import { CONTROLLER_HELPER } from '@constants/address' const useStyles = makeStyles((theme) => createStyles({ @@ -94,6 +92,7 @@ const useStyles = makeStyles((theme) => export function LPCalculator() { const [isVaultApproved, setIsVaultApproved] = useState(true) + const { controllerHelper } = useAtomValue(addressesAtom) const classes = useStyles() const { isRestricted } = useRestrictUser() const ethPrice = useETHPrice() @@ -103,45 +102,45 @@ export function LPCalculator() { const openLPPosition = useOpenPositionDeposit() const closeLPPosition = useClosePosition() const collectFees = useCollectFees() - const rebalanceVault = useRebalanceVault() const rebalanceSwap = useRebalanceGeneralSwap() + const updateOperator = useUpdateOperator() const { vaultId, validVault: vault } = useFirstValidVault() const openPos = useAppCallback(async () => { try { - await openLPPosition(new BigNumber(50), -887220, 887220, 0, () => {}) + await openLPPosition(new BigNumber(200), -887220, 887220, 0, () => {}) } catch (e) { console.log(e) } }, [vaultId, squeethPrice]) - const collFees = useAppCallback(async () => { + const updateOp = useAppCallback(async () => { try { - await collectFees(Number(682), () => {}) + await updateOperator(Number(682), controllerHelper) } catch (e) { console.log(e) } }, [vaultId]) - const closePos = useAppCallback(async () => { + const collFees = useAppCallback(async () => { try { - await closeLPPosition(Number(682), () => {}) + await collectFees(Number(682), () => {}) } catch (e) { console.log(e) } }, [vaultId]) - const rebalVault = useAppCallback(async () => { + const closePos = useAppCallback(async () => { try { - await rebalanceVault(Number(682), -887220, 887220, () => {}) + await closeLPPosition(Number(682), () => {}) } catch (e) { console.log(e) } -}, [vaultId]) + }, [vaultId]) const rebalSwap = useAppCallback(async () => { try { - await rebalanceSwap(Number(682), 0, 80000, () => {}) + await rebalanceSwap(Number(682), -20, 500, () => {}) } catch (e) { console.log(e) } @@ -235,36 +234,36 @@ export function LPCalculator() { - - - - - - - - -
) : (
@@ -336,4 +402,4 @@ export function LPage() { ) } -export default LPage \ No newline at end of file +export default LPage From 67d4fa66c48da7d11f88515b9d092904f807b551 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 9 Aug 2022 20:44:23 -0700 Subject: [PATCH 73/82] dependencies --- packages/frontend/pages/lp.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index f53d763e1..306f913be 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -135,7 +135,7 @@ export function LPCalculator() { } catch (e) { console.log(e) } - }, [vaultID, squeethPrice, openLPPosition]) + }, [squeethAmount, vaultID, lowerTick, upperTick, collatRatio, slippage, collatToWithdraw, openLPPosition]) const updateOp = useAppCallback(async () => { try { @@ -143,7 +143,7 @@ export function LPCalculator() { } catch (e) { console.log(e) } - }, [vaultID, updateOperator]) + }, [vaultID, controllerHelper, updateOperator]) const collFees = useAppCallback(async () => { try { @@ -155,7 +155,6 @@ export function LPCalculator() { const closePos = useAppCallback(async () => { try { - console.log("vault id", vaultID) await closeLPPosition( vaultID, liquidityPercentage, @@ -168,7 +167,7 @@ export function LPCalculator() { } catch (e) { console.log(e) } - }, [vaultID, closeLPPosition]) + }, [vaultID, liquidityPercentage, burnPercentage, collatToWithdraw, burnExactRemoved, slippage, closeLPPosition]) const rebalSwap = useAppCallback(async () => { try { @@ -176,7 +175,7 @@ export function LPCalculator() { } catch (e) { console.log(e) } - }, [vaultID, rebalanceSwap]) + }, [vaultID, lowerTick, upperTick, slippage, rebalanceSwap]) return (
From 8b4f968b58b7ef81ab2f07a180cdae7383fc1261 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Fri, 12 Aug 2022 22:48:17 -0700 Subject: [PATCH 74/82] remove pool state dupe --- packages/frontend/src/state/lp/hooks.ts | 25 ++----------------- .../frontend/src/state/squeethPool/hooks.ts | 10 +++++--- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 487aa67a0..3078a88c4 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -12,6 +12,7 @@ import { useHandleTransaction } from '../wallet/hooks' import { ethers } from 'ethers' import { useCallback } from 'react' import { useGetDebtAmount, useGetVault } from '../controller/hooks' +import { getPoolState } from '../squeethPool/hooks' /*** CONSTANTS ***/ const COLLAT_RATIO_FLASHLOAN = 2 @@ -479,26 +480,4 @@ export const useGetPosition = () => { ) return getExactOut - } - - async function getPoolState(poolContract: Contract) { - const [slot, liquidity, tickSpacing] = await Promise.all([ - poolContract?.methods.slot0().call(), - poolContract?.methods.liquidity().call(), - poolContract.methods.tickSpacing().call() - ]) - - const PoolState = { - liquidity, - sqrtPriceX96: slot[0], - tick: slot[1], - observationIndex: slot[2], - observationCardinality: slot[3], - observationCardinalityNext: slot[4], - feeProtocol: slot[5], - unlocked: slot[6], - tickSpacing - } - - return PoolState - } \ No newline at end of file + } \ No newline at end of file diff --git a/packages/frontend/src/state/squeethPool/hooks.ts b/packages/frontend/src/state/squeethPool/hooks.ts index f05380b90..4c67d2173 100644 --- a/packages/frontend/src/state/squeethPool/hooks.ts +++ b/packages/frontend/src/state/squeethPool/hooks.ts @@ -47,10 +47,11 @@ const getImmutables = async (squeethContract: Contract) => { return { token0, token1, fee, tickSpacing, maxLiquidityPerTick } } -async function getPoolState(squeethContract: Contract) { - const [slot, liquidity] = await Promise.all([ - squeethContract?.methods.slot0().call(), - squeethContract?.methods.liquidity().call(), +export const getPoolState = async (poolContract: Contract) => { + const [slot, liquidity, tickSpacing] = await Promise.all([ + poolContract?.methods.slot0().call(), + poolContract?.methods.liquidity().call(), + poolContract.methods.tickSpacing().call() ]) const PoolState = { @@ -62,6 +63,7 @@ async function getPoolState(squeethContract: Contract) { observationCardinalityNext: slot[4], feeProtocol: slot[5], unlocked: slot[6], + tickSpacing } return PoolState From 8552d4c77998861613647267121de23f96fcf948 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 16 Aug 2022 20:59:30 -0700 Subject: [PATCH 75/82] things --- packages/frontend/src/state/lp/hooks.ts | 90 +++++++++++++++++++------ 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 3078a88c4..78b209062 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -1,9 +1,9 @@ import { nearestUsableTick, TickMath } from '@uniswap/v3-sdk' -import { fromTokenAmount } from '@utils/calculations' +import { fromTokenAmount, toTokenAmount } from '@utils/calculations' import { useAtomValue } from 'jotai' import { addressesAtom, isWethToken0Atom } from '../positions/atoms' import BigNumber from 'bignumber.js' -import { OSQUEETH_DECIMALS } from '@constants/index' +import { INDEX_SCALE, OSQUEETH_DECIMALS, WETH_DECIMALS } from '@constants/index' import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom, quoterContractAtom, squeethPoolContractAtom } from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' import { addressAtom } from '../wallet/atoms' @@ -13,12 +13,14 @@ import { ethers } from 'ethers' import { useCallback } from 'react' import { useGetDebtAmount, useGetVault } from '../controller/hooks' import { getPoolState } from '../squeethPool/hooks' +import { indexAtom, normFactorAtom } from '../controller/atoms' /*** CONSTANTS ***/ const COLLAT_RATIO_FLASHLOAN = 2 const POOL_FEE = 3000 const MAX_INT_128 = new BigNumber(2).pow(128).minus(1).toFixed(0) const x96 = new BigNumber(2).pow(96) +const FLASHLOAN_BUFFER = 0.02 /*** ACTIONS ***/ @@ -31,9 +33,13 @@ export const useOpenPositionDeposit = () => { const getDebtAmount = useGetDebtAmount() const squeethPoolContract = useAtomValue(squeethPoolContractAtom) const isWethToken0 = useAtomValue(isWethToken0Atom) + const index = useAtomValue(indexAtom) + const normFactor = useAtomValue(normFactorAtom) + const getVault = useGetVault() const openPositionDeposit = useAppCallback( async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, vaultId: number, collatRatio: number, slippage: number, withdrawAmount: number, onTxConfirmed?: () => void) => { - if (!contract || !address || !squeethPoolContract) return null + const vaultBefore = await getVault(vaultId) + if (!contract || !address || !squeethPoolContract || !vaultBefore || !vaultBefore.shortAmount || !vaultBefore.collateralAmount) return null const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) const ethDebtPromise = getDebtAmount(mintWSqueethAmount) @@ -48,28 +54,72 @@ export const useOpenPositionDeposit = () => { const squeethPrice = isWethToken0 ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2)) : new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2) const sqrtSqueethPrice = squeethPrice.sqrt() - const collateralToMint = ethDebt.multipliedBy(collatRatio) - - // Lx = x * (sqrtSqueethPrice * sqrtUpperPrice) / (sqrtUpperPrice - sqrtSqueethPrice) - // y = Lx * (sqrtSqueethPrice - sqrtLowerPrice) - const liquidity = mintWSqueethAmount.times(sqrtSqueethPrice.times(sqrtUpperPrice)).div(sqrtUpperPrice.minus(sqrtSqueethPrice)) - const collateralToLp = sqrtUpperPrice.lt(sqrtSqueethPrice) ? liquidity.times(sqrtUpperPrice.minus(sqrtLowerPrice)) - : sqrtSqueethPrice.lt(sqrtLowerPrice) ? new BigNumber(0) - : liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) - - const amount0 = isWethToken0 ? collateralToLp : mintWSqueethAmount - const amount1 = isWethToken0 ? mintWSqueethAmount : collateralToLp - const amount0Min = amount0.times(new BigNumber(1).minus(slippage)).toFixed(0) - const amount1Min = amount1.times(new BigNumber(1).minus(slippage)).toFixed(0) - const collateralToWithdraw = new BigNumber(withdrawAmount) + let collateralToLp + if (sqrtUpperPrice.lt(sqrtSqueethPrice)) { + // All weth position + console.log("all weth pos") + console.log("LPing an all WETH position is not enabled, but you can rebalance to this position.") + return + } else if (sqrtSqueethPrice.lt(sqrtLowerPrice)) { + // All squeeth position + collateralToLp = new BigNumber(0) + } else { + // Lx = x * (sqrtSqueethPrice * sqrtUpperPrice) / (sqrtUpperPrice - sqrtSqueethPrice) + // y = Lx * (sqrtSqueethPrice - sqrtLowerPrice) + const liquidity = mintWSqueethAmount.times(sqrtSqueethPrice.times(sqrtUpperPrice)).div(sqrtUpperPrice.minus(sqrtSqueethPrice)) + collateralToLp = sqrtUpperPrice.lt(sqrtSqueethPrice) ? liquidity.times(sqrtUpperPrice.minus(sqrtLowerPrice)) + : sqrtSqueethPrice.lt(sqrtLowerPrice) ? new BigNumber(0) + : liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) + + } + console.log("collateralToLp", collateralToLp.toString()) + + const amount0New = isWethToken0 ? collateralToLp : mintWSqueethAmount + const amount1New = isWethToken0 ? mintWSqueethAmount : collateralToLp + const amount0Min = amount0New.times(new BigNumber(1).minus(slippage)).toFixed(0) + const amount1Min = amount1New.times(new BigNumber(1).minus(slippage)).toFixed(0) + + const collateralToWithdraw = fromTokenAmount(withdrawAmount, OSQUEETH_DECIMALS) + const ethIndexPrice = toTokenAmount(index, 18).sqrt() + const vaultShortAmt = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS) + + // const collateralToMint = ethDebt.multipliedBy(collatRatio) + + // Calculate collateralToMint + const collateralToMintNew = (new BigNumber(collatRatio).times((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE))) + .minus((vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus((mintWSqueethAmount).times(squeethPrice)))) + const collateralToMintTest = BigNumber.max(collateralToMintNew, 0).plus(9000000000000000000) + const collateralToMintOld = ethDebt.times(collatRatio) + console.log("first term", (new BigNumber(collatRatio).times((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE))).toString()) + console.log("second term", (vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus((mintWSqueethAmount).times(squeethPrice))).toString()) + console.log("vaultCollateralAmt", vaultCollateralAmt.toString()) + console.log("collateralToWithdraw", collateralToWithdraw.toString()) + console.log("collateralToLp", collateralToLp.toString()) + console.log("(mintWSqueethAmount).times(ethIndexPrice)", (mintWSqueethAmount).times(squeethPrice).toString()) + + const CR = (vaultCollateralAmt.plus(collateralToMintNew).minus(collateralToWithdraw).plus(collateralToLp).plus((mintWSqueethAmount).times(squeethPrice))) + .div((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) + console.log("debt", (vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE).toString()) + console.log("collateralToMintNew", collateralToMintNew.toString()) + + console.log("collateralToMint",collateralToMintNew.toString()) + const flashLoanAmount = (new BigNumber(1.5 + FLASHLOAN_BUFFER).times(vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) + .minus(vaultCollateralAmt.plus(collateralToMintNew).minus(collateralToWithdraw)) + console.log("flashLoanAmount", flashLoanAmount.toString()) + console.log("vaultBefore.shortAmount", vaultBefore.shortAmount.toString()) + console.log("vaultBefore.collateralAmount", vaultCollateralAmt.toString()) + console.log("normFactor", normFactor.toString()) + console.log("ethIndexPrice", ethIndexPrice.toString()) + console.log("C R", CR.toString()) const flashloanWMintDepositNftParams = { wPowerPerpPool: squeethPool, vaultId: vaultId, wPowerPerpAmount: mintWSqueethAmount.toFixed(0), - collateralToDeposit: collateralToMint.toFixed(0), - collateralToFlashloan: collateralToMint.toFixed(0), + collateralToDeposit: BigNumber.max(collateralToMintNew, 0).plus(BigNumber.max(flashLoanAmount, 0)).toFixed(0), + collateralToFlashloan: BigNumber.max(flashLoanAmount, 0).toFixed(0), collateralToLp: collateralToLp.toFixed(0), collateralToWithdraw: collateralToWithdraw.toFixed(0), amount0Min, @@ -81,7 +131,7 @@ export const useOpenPositionDeposit = () => { return handleTransaction( contract.methods.flashloanWMintLpDepositNft(flashloanWMintDepositNftParams).send({ from: address, - value: collateralToLp.plus(collateralToMint).minus(collateralToWithdraw).toFixed(0), + value: collateralToLp.plus(BigNumber.max(collateralToMintNew, 0)).minus(collateralToWithdraw).toFixed(0), }), onTxConfirmed, ) From bf0fe9beb93099564850b118e34936343ef4c2ae Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Wed, 17 Aug 2022 01:51:35 -0700 Subject: [PATCH 76/82] format --- packages/frontend/src/state/lp/hooks.ts | 48 ++++++------------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 78b209062..0389c40ec 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -42,11 +42,9 @@ export const useOpenPositionDeposit = () => { if (!contract || !address || !squeethPoolContract || !vaultBefore || !vaultBefore.shortAmount || !vaultBefore.collateralAmount) return null const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) - const ethDebtPromise = getDebtAmount(mintWSqueethAmount) - const poolStatePromise = getPoolState(squeethPoolContract) // Calculate prices from ticks - const [ethDebt, { tick, tickSpacing }] = await Promise.all([ethDebtPromise, poolStatePromise]) + const { tick, tickSpacing } = await getPoolState(squeethPoolContract) const lowerTick = nearestUsableTick(lowerTickInput, Number(tickSpacing)) const upperTick = nearestUsableTick(upperTickInput, Number(tickSpacing)) const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(lowerTick).toString()).div(x96) @@ -58,7 +56,6 @@ export const useOpenPositionDeposit = () => { let collateralToLp if (sqrtUpperPrice.lt(sqrtSqueethPrice)) { // All weth position - console.log("all weth pos") console.log("LPing an all WETH position is not enabled, but you can rebalance to this position.") return } else if (sqrtSqueethPrice.lt(sqrtLowerPrice)) { @@ -71,9 +68,7 @@ export const useOpenPositionDeposit = () => { collateralToLp = sqrtUpperPrice.lt(sqrtSqueethPrice) ? liquidity.times(sqrtUpperPrice.minus(sqrtLowerPrice)) : sqrtSqueethPrice.lt(sqrtLowerPrice) ? new BigNumber(0) : liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) - } - console.log("collateralToLp", collateralToLp.toString()) const amount0New = isWethToken0 ? collateralToLp : mintWSqueethAmount const amount1New = isWethToken0 ? mintWSqueethAmount : collateralToLp @@ -85,41 +80,20 @@ export const useOpenPositionDeposit = () => { const vaultShortAmt = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS) - // const collateralToMint = ethDebt.multipliedBy(collatRatio) - - // Calculate collateralToMint - const collateralToMintNew = (new BigNumber(collatRatio).times((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE))) + const collateralToMint = (new BigNumber(collatRatio).times((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE))) .minus((vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus((mintWSqueethAmount).times(squeethPrice)))) - const collateralToMintTest = BigNumber.max(collateralToMintNew, 0).plus(9000000000000000000) - const collateralToMintOld = ethDebt.times(collatRatio) - console.log("first term", (new BigNumber(collatRatio).times((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE))).toString()) - console.log("second term", (vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus((mintWSqueethAmount).times(squeethPrice))).toString()) - console.log("vaultCollateralAmt", vaultCollateralAmt.toString()) - console.log("collateralToWithdraw", collateralToWithdraw.toString()) - console.log("collateralToLp", collateralToLp.toString()) - console.log("(mintWSqueethAmount).times(ethIndexPrice)", (mintWSqueethAmount).times(squeethPrice).toString()) - - const CR = (vaultCollateralAmt.plus(collateralToMintNew).minus(collateralToWithdraw).plus(collateralToLp).plus((mintWSqueethAmount).times(squeethPrice))) - .div((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) - console.log("debt", (vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE).toString()) - console.log("collateralToMintNew", collateralToMintNew.toString()) - - console.log("collateralToMint",collateralToMintNew.toString()) - const flashLoanAmount = (new BigNumber(1.5 + FLASHLOAN_BUFFER).times(vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) - .minus(vaultCollateralAmt.plus(collateralToMintNew).minus(collateralToWithdraw)) - console.log("flashLoanAmount", flashLoanAmount.toString()) - console.log("vaultBefore.shortAmount", vaultBefore.shortAmount.toString()) - console.log("vaultBefore.collateralAmount", vaultCollateralAmt.toString()) - console.log("normFactor", normFactor.toString()) - console.log("ethIndexPrice", ethIndexPrice.toString()) - console.log("C R", CR.toString()) + const flashLoanAmount = (new BigNumber(collatRatio + FLASHLOAN_BUFFER).times(vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) + .minus(vaultCollateralAmt.plus(collateralToMint).minus(collateralToWithdraw)) + const collateralToMintPos = BigNumber.max(collateralToMint, 0) + const flashLoanAmountPos = BigNumber.max(flashLoanAmount, 0) + const flashloanWMintDepositNftParams = { wPowerPerpPool: squeethPool, vaultId: vaultId, wPowerPerpAmount: mintWSqueethAmount.toFixed(0), - collateralToDeposit: BigNumber.max(collateralToMintNew, 0).plus(BigNumber.max(flashLoanAmount, 0)).toFixed(0), - collateralToFlashloan: BigNumber.max(flashLoanAmount, 0).toFixed(0), + collateralToDeposit: collateralToMintPos.plus(flashLoanAmountPos).toFixed(0), + collateralToFlashloan: flashLoanAmountPos.toFixed(0), collateralToLp: collateralToLp.toFixed(0), collateralToWithdraw: collateralToWithdraw.toFixed(0), amount0Min, @@ -131,12 +105,12 @@ export const useOpenPositionDeposit = () => { return handleTransaction( contract.methods.flashloanWMintLpDepositNft(flashloanWMintDepositNftParams).send({ from: address, - value: collateralToLp.plus(BigNumber.max(collateralToMintNew, 0)).minus(collateralToWithdraw).toFixed(0), + value: collateralToLp.plus(collateralToMintPos).minus(collateralToWithdraw).toFixed(0), }), onTxConfirmed, ) }, - [address, squeethPool, contract, handleTransaction, getDebtAmount, squeethPoolContract, isWethToken0], + [address, squeethPool, contract, handleTransaction, getDebtAmount, squeethPoolContract, isWethToken0, index, normFactor, getVault], ) return openPositionDeposit From 4af4e5c0f0ec560a9d865a96fb09d272fdfc77f4 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 18 Aug 2022 18:31:55 -0700 Subject: [PATCH 77/82] open bounds --- packages/frontend/src/state/lp/hooks.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 0389c40ec..8a1f56777 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -47,10 +47,15 @@ export const useOpenPositionDeposit = () => { const { tick, tickSpacing } = await getPoolState(squeethPoolContract) const lowerTick = nearestUsableTick(lowerTickInput, Number(tickSpacing)) const upperTick = nearestUsableTick(upperTickInput, Number(tickSpacing)) - const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(lowerTick).toString()).div(x96) - const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(upperTick).toString()).div(x96) + const lowerPrice = isWethToken0 ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(lowerTick)).toString()).div(x96).pow(2)) + : new BigNumber(TickMath.getSqrtRatioAtTick(Number(lowerTick)).toString()).div(x96).pow(2) + const upperPrice = isWethToken0 ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(upperTick)).toString()).div(x96).pow(2)) + : new BigNumber(TickMath.getSqrtRatioAtTick(Number(upperTick)).toString()).div(x96).pow(2) const squeethPrice = isWethToken0 ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2)) - : new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2) + : new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2) + + const sqrtLowerPrice = lowerPrice.sqrt() + const sqrtUpperPrice = upperPrice.sqrt() const sqrtSqueethPrice = squeethPrice.sqrt() let collateralToLp From d72265d57c8cd6ecd3a8889f6f64343ed49aa2cb Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 18 Aug 2022 19:24:21 -0700 Subject: [PATCH 78/82] open --- packages/frontend/src/state/lp/hooks.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 8a1f56777..68da97277 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -70,9 +70,7 @@ export const useOpenPositionDeposit = () => { // Lx = x * (sqrtSqueethPrice * sqrtUpperPrice) / (sqrtUpperPrice - sqrtSqueethPrice) // y = Lx * (sqrtSqueethPrice - sqrtLowerPrice) const liquidity = mintWSqueethAmount.times(sqrtSqueethPrice.times(sqrtUpperPrice)).div(sqrtUpperPrice.minus(sqrtSqueethPrice)) - collateralToLp = sqrtUpperPrice.lt(sqrtSqueethPrice) ? liquidity.times(sqrtUpperPrice.minus(sqrtLowerPrice)) - : sqrtSqueethPrice.lt(sqrtLowerPrice) ? new BigNumber(0) - : liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) + collateralToLp = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) } const amount0New = isWethToken0 ? collateralToLp : mintWSqueethAmount @@ -86,9 +84,10 @@ export const useOpenPositionDeposit = () => { const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS) // Calculate collateralToMint + const oSQTHInETH = mintWSqueethAmount.times(ethIndexPrice.div(INDEX_SCALE)).times(normFactor) const collateralToMint = (new BigNumber(collatRatio).times((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE))) - .minus((vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus((mintWSqueethAmount).times(squeethPrice)))) - const flashLoanAmount = (new BigNumber(collatRatio + FLASHLOAN_BUFFER).times(vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) + .minus((vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus(oSQTHInETH))) + const flashLoanAmount = (new BigNumber(COLLAT_RATIO_FLASHLOAN + FLASHLOAN_BUFFER).times(vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) .minus(vaultCollateralAmt.plus(collateralToMint).minus(collateralToWithdraw)) const collateralToMintPos = BigNumber.max(collateralToMint, 0) const flashLoanAmountPos = BigNumber.max(flashLoanAmount, 0) From fccd68d7cbf8196f842fb8f3367394e6e7b7040e Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Tue, 23 Aug 2022 15:59:09 -0700 Subject: [PATCH 79/82] symmetry --- packages/frontend/src/state/lp/hooks.ts | 716 +++++++++++++++--------- 1 file changed, 454 insertions(+), 262 deletions(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 68da97277..51c46929e 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -4,7 +4,13 @@ import { useAtomValue } from 'jotai' import { addressesAtom, isWethToken0Atom } from '../positions/atoms' import BigNumber from 'bignumber.js' import { INDEX_SCALE, OSQUEETH_DECIMALS, WETH_DECIMALS } from '@constants/index' -import { controllerContractAtom, controllerHelperHelperContractAtom, nftManagerContractAtom, quoterContractAtom, squeethPoolContractAtom } from '../contracts/atoms' +import { + controllerContractAtom, + controllerHelperHelperContractAtom, + nftManagerContractAtom, + quoterContractAtom, + squeethPoolContractAtom, +} from '../contracts/atoms' import useAppCallback from '@hooks/useAppCallback' import { addressAtom } from '../wallet/atoms' import { Contract } from 'web3-eth-contract' @@ -36,42 +42,38 @@ export const useOpenPositionDeposit = () => { const index = useAtomValue(indexAtom) const normFactor = useAtomValue(normFactorAtom) const getVault = useGetVault() + const getCollateralToLP = useGetCollateralToLP() const openPositionDeposit = useAppCallback( - async (squeethToMint: BigNumber, lowerTickInput: number, upperTickInput: number, vaultId: number, collatRatio: number, slippage: number, withdrawAmount: number, onTxConfirmed?: () => void) => { + async ( + squeethToMint: BigNumber, + lowerTickInput: number, + upperTickInput: number, + vaultId: number, + collatRatio: number, + slippage: number, + withdrawAmount: number, + onTxConfirmed?: () => void, + ) => { const vaultBefore = await getVault(vaultId) - if (!contract || !address || !squeethPoolContract || !vaultBefore || !vaultBefore.shortAmount || !vaultBefore.collateralAmount) return null - - const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) + if ( + !contract || + !address || + !squeethPoolContract || + !vaultBefore || + !vaultBefore.shortAmount || + !vaultBefore.collateralAmount + ) + return null - // Calculate prices from ticks + const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS) const { tick, tickSpacing } = await getPoolState(squeethPoolContract) const lowerTick = nearestUsableTick(lowerTickInput, Number(tickSpacing)) const upperTick = nearestUsableTick(upperTickInput, Number(tickSpacing)) - const lowerPrice = isWethToken0 ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(lowerTick)).toString()).div(x96).pow(2)) - : new BigNumber(TickMath.getSqrtRatioAtTick(Number(lowerTick)).toString()).div(x96).pow(2) - const upperPrice = isWethToken0 ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(upperTick)).toString()).div(x96).pow(2)) - : new BigNumber(TickMath.getSqrtRatioAtTick(Number(upperTick)).toString()).div(x96).pow(2) - const squeethPrice = isWethToken0 ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2)) - : new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2) - - const sqrtLowerPrice = lowerPrice.sqrt() - const sqrtUpperPrice = upperPrice.sqrt() - const sqrtSqueethPrice = squeethPrice.sqrt() + console.log("upperTick", upperTick) - let collateralToLp - if (sqrtUpperPrice.lt(sqrtSqueethPrice)) { - // All weth position - console.log("LPing an all WETH position is not enabled, but you can rebalance to this position.") - return - } else if (sqrtSqueethPrice.lt(sqrtLowerPrice)) { - // All squeeth position - collateralToLp = new BigNumber(0) - } else { - // Lx = x * (sqrtSqueethPrice * sqrtUpperPrice) / (sqrtUpperPrice - sqrtSqueethPrice) - // y = Lx * (sqrtSqueethPrice - sqrtLowerPrice) - const liquidity = mintWSqueethAmount.times(sqrtSqueethPrice.times(sqrtUpperPrice)).div(sqrtUpperPrice.minus(sqrtSqueethPrice)) - collateralToLp = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) - } + const collateralToLp = await getCollateralToLP(mintWSqueethAmount, lowerTick, upperTick, tick) + if (!collateralToLp) return + console.log("collateralToLp", collateralToLp.toString()) const amount0New = isWethToken0 ? collateralToLp : mintWSqueethAmount const amount1New = isWethToken0 ? mintWSqueethAmount : collateralToLp @@ -82,13 +84,18 @@ export const useOpenPositionDeposit = () => { const ethIndexPrice = toTokenAmount(index, 18).sqrt() const vaultShortAmt = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS) - + // Calculate collateralToMint const oSQTHInETH = mintWSqueethAmount.times(ethIndexPrice.div(INDEX_SCALE)).times(normFactor) - const collateralToMint = (new BigNumber(collatRatio).times((vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE))) - .minus((vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus(oSQTHInETH))) - const flashLoanAmount = (new BigNumber(COLLAT_RATIO_FLASHLOAN + FLASHLOAN_BUFFER).times(vaultShortAmt.plus(mintWSqueethAmount)).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) - .minus(vaultCollateralAmt.plus(collateralToMint).minus(collateralToWithdraw)) + const collateralToMint = new BigNumber(collatRatio) + .times(vaultShortAmt.plus(mintWSqueethAmount).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE)) + .minus(vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus(oSQTHInETH)) + const flashLoanAmount = new BigNumber(COLLAT_RATIO_FLASHLOAN + FLASHLOAN_BUFFER) + .times(vaultShortAmt.plus(mintWSqueethAmount)) + .times(normFactor) + .times(ethIndexPrice) + .div(INDEX_SCALE) + .minus(vaultCollateralAmt.plus(collateralToMint).minus(collateralToWithdraw)) const collateralToMintPos = BigNumber.max(collateralToMint, 0) const flashLoanAmountPos = BigNumber.max(flashLoanAmount, 0) @@ -114,7 +121,18 @@ export const useOpenPositionDeposit = () => { onTxConfirmed, ) }, - [address, squeethPool, contract, handleTransaction, getDebtAmount, squeethPoolContract, isWethToken0, index, normFactor, getVault], + [ + address, + squeethPool, + contract, + handleTransaction, + getDebtAmount, + squeethPoolContract, + isWethToken0, + index, + normFactor, + getVault, + ], ) return openPositionDeposit @@ -133,63 +151,101 @@ export const useClosePosition = () => { const getExactOut = useGetExactOut() const getDecreaseLiquidity = useGetDecreaseLiquidity() const isWethToken0 = useAtomValue(isWethToken0Atom) - const closePosition = useAppCallback(async (vaultId: number, liquidityPercentage: number, burnPercentage: number, collateralToWithdraw: number, burnExactRemoved: boolean, slippage: number, onTxConfirmed?: () => void) => { - const vaultBefore = await getVault(vaultId) - const uniTokenId = vaultBefore?.NFTCollateralId - const position = await getPosition(uniTokenId) - - if ( - !controllerContract || - !controllerHelperContract || - !address || - !position || - !vaultBefore || - !vaultBefore.shortAmount - ) - return - - const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) - const debtInEthPromise = getDebtAmount(shortAmount) - - // Get current LP positions - const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) - const wPowerPerpAmountInLP = isWethToken0 ? amount1 : amount0 - - const amountToLiquidate = new BigNumber(wPowerPerpAmountInLP).times(liquidityPercentage) - const amountToBurn = shortAmount.times(burnPercentage) - const limitEthPromise = amountToLiquidate.gt(amountToBurn) ? getExactIn(amountToLiquidate.minus(amountToBurn), true) - : getExactOut(amountToBurn.minus(amountToLiquidate), true) - - const [debtInEth, limitEth] = await Promise.all([debtInEthPromise, limitEthPromise]) - const limitPrice = new BigNumber(limitEth).div(amountToLiquidate.minus(amountToBurn).abs()).times(new BigNumber(1).minus(slippage)) - - const collateralToFlashloan = debtInEth.multipliedBy(COLLAT_RATIO_FLASHLOAN) - - const amount0Min = new BigNumber(amount0).times(liquidityPercentage).times(new BigNumber(1).minus(slippage)).toFixed(0) - const amount1Min = new BigNumber(amount1).times(liquidityPercentage).times(new BigNumber(1).minus(slippage)).toFixed(0) - - const flashloanCloseVaultLpNftParam = { - vaultId: vaultId, - tokenId: uniTokenId, - liquidity: position.liquidity, - liquidityPercentage: fromTokenAmount(liquidityPercentage, 18).toFixed(0), - wPowerPerpAmountToBurn: amountToBurn.toFixed(0), - collateralToFlashloan: collateralToFlashloan.toFixed(0), - collateralToWithdraw: collateralToWithdraw.toFixed(0), - limitPriceEthPerPowerPerp: fromTokenAmount(limitPrice, 18).toFixed(0), - amount0Min, - amount1Min, - poolFee: POOL_FEE, - burnExactRemoved, - } - - return handleTransaction( - await controllerHelperContract.methods.flashloanCloseVaultLpNft(flashloanCloseVaultLpNftParam).send({ - from: address, - }), - onTxConfirmed, - ) - }, [address, controllerHelperContract, controllerContract, handleTransaction, getDebtAmount, getVault, getPosition, getExactIn, getExactOut, getDecreaseLiquidity, isWethToken0]) + const closePosition = useAppCallback( + async ( + vaultId: number, + liquidityPercentage: number, + burnPercentage: number, + collateralToWithdraw: number, + burnExactRemoved: boolean, + slippage: number, + onTxConfirmed?: () => void, + ) => { + const vaultBefore = await getVault(vaultId) + const uniTokenId = vaultBefore?.NFTCollateralId + const position = await getPosition(uniTokenId) + + if ( + !controllerContract || + !controllerHelperContract || + !address || + !position || + !vaultBefore || + !vaultBefore.shortAmount + ) + return + + const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + const debtInEthPromise = getDebtAmount(shortAmount) + + // Get current LP positions + const { amount0, amount1 } = await getDecreaseLiquidity( + uniTokenId, + position.liquidity, + 0, + 0, + Math.floor(Date.now() / 1000 + 86400), + ) + const wPowerPerpAmountInLP = isWethToken0 ? amount1 : amount0 + + const amountToLiquidate = new BigNumber(wPowerPerpAmountInLP).times(liquidityPercentage) + const amountToBurn = shortAmount.times(burnPercentage) + const limitEthPromise = amountToLiquidate.gt(amountToBurn) + ? getExactIn(amountToLiquidate.minus(amountToBurn), true) + : getExactOut(amountToBurn.minus(amountToLiquidate), true) + + const [debtInEth, limitEth] = await Promise.all([debtInEthPromise, limitEthPromise]) + const limitPrice = new BigNumber(limitEth) + .div(amountToLiquidate.minus(amountToBurn).abs()) + .times(new BigNumber(1).minus(slippage)) + + const collateralToFlashloan = debtInEth.multipliedBy(COLLAT_RATIO_FLASHLOAN) + + const amount0Min = new BigNumber(amount0) + .times(liquidityPercentage) + .times(new BigNumber(1).minus(slippage)) + .toFixed(0) + const amount1Min = new BigNumber(amount1) + .times(liquidityPercentage) + .times(new BigNumber(1).minus(slippage)) + .toFixed(0) + + const flashloanCloseVaultLpNftParam = { + vaultId: vaultId, + tokenId: uniTokenId, + liquidity: position.liquidity, + liquidityPercentage: fromTokenAmount(liquidityPercentage, 18).toFixed(0), + wPowerPerpAmountToBurn: amountToBurn.toFixed(0), + collateralToFlashloan: collateralToFlashloan.toFixed(0), + collateralToWithdraw: collateralToWithdraw.toFixed(0), + limitPriceEthPerPowerPerp: fromTokenAmount(limitPrice, 18).toFixed(0), + amount0Min, + amount1Min, + poolFee: POOL_FEE, + burnExactRemoved, + } + + return handleTransaction( + await controllerHelperContract.methods.flashloanCloseVaultLpNft(flashloanCloseVaultLpNftParam).send({ + from: address, + }), + onTxConfirmed, + ) + }, + [ + address, + controllerHelperContract, + controllerContract, + handleTransaction, + getDebtAmount, + getVault, + getPosition, + getExactIn, + getExactOut, + getDecreaseLiquidity, + isWethToken0, + ], + ) return closePosition } @@ -201,48 +257,51 @@ export const useCollectFees = () => { const handleTransaction = useHandleTransaction() const getDebtAmount = useGetDebtAmount() const getVault = useGetVault() - const collectFees = useAppCallback(async (vaultId: number, onTxConfirmed?: () => void) => { - const vaultBefore = await getVault(vaultId) - const uniTokenId = vaultBefore?.NFTCollateralId - - if ( - !controllerContract || - !controllerHelperContract || - !address || - !vaultBefore || - !vaultBefore.shortAmount || - !uniTokenId - ) - return - - const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) - const debtInEth = await getDebtAmount(shortAmount) - const collateralToFlashloan = debtInEth.multipliedBy(COLLAT_RATIO_FLASHLOAN) - const amount0Max = MAX_INT_128 - const amount1Max = MAX_INT_128 - const abiCoder = new ethers.utils.AbiCoder() - const rebalanceLpInVaultParams = [ - { - rebalanceLpInVaultType: new BigNumber(6).toFixed(0), - // CollectFees - data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [uniTokenId, amount0Max, amount1Max]), - }, - { - rebalanceLpInVaultType: new BigNumber(7).toFixed(0), - // DepositExistingNftParams - data: abiCoder.encode(["uint256"], [uniTokenId]) - } - ] + const collectFees = useAppCallback( + async (vaultId: number, onTxConfirmed?: () => void) => { + const vaultBefore = await getVault(vaultId) + const uniTokenId = vaultBefore?.NFTCollateralId + + if ( + !controllerContract || + !controllerHelperContract || + !address || + !vaultBefore || + !vaultBefore.shortAmount || + !uniTokenId + ) + return - return handleTransaction( - await controllerHelperContract.methods - .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) - .send({ - from: address, - }), - onTxConfirmed, - ) - }, [address, controllerHelperContract, controllerContract, handleTransaction, getDebtAmount, getVault]) + const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + const debtInEth = await getDebtAmount(shortAmount) + const collateralToFlashloan = debtInEth.multipliedBy(COLLAT_RATIO_FLASHLOAN) + const amount0Max = MAX_INT_128 + const amount1Max = MAX_INT_128 + const abiCoder = new ethers.utils.AbiCoder() + const rebalanceLpInVaultParams = [ + { + rebalanceLpInVaultType: new BigNumber(6).toFixed(0), + // CollectFees + data: abiCoder.encode(['uint256', 'uint128', 'uint128'], [uniTokenId, amount0Max, amount1Max]), + }, + { + rebalanceLpInVaultType: new BigNumber(7).toFixed(0), + // DepositExistingNftParams + data: abiCoder.encode(['uint256'], [uniTokenId]), + }, + ] + + return handleTransaction( + await controllerHelperContract.methods + .rebalanceLpInVault(vaultId, collateralToFlashloan.toFixed(0), rebalanceLpInVaultParams) + .send({ + from: address, + }), + onTxConfirmed, + ) + }, + [address, controllerHelperContract, controllerContract, handleTransaction, getDebtAmount, getVault], + ) return collectFees } @@ -262,18 +321,38 @@ export const useRebalanceGeneralSwap = () => { const getExactIn = useGetExactIn() const getExactOut = useGetExactOut() const rebalanceGeneralSwap = useAppCallback( - async (vaultId: number, lowerTickInput: number, upperTickInput: number, slippage: number, onTxConfirmed?: () => void) => { + async ( + vaultId: number, + lowerTickInput: number, + upperTickInput: number, + slippage: number, + onTxConfirmed?: () => void, + ) => { const vaultBefore = await getVault(vaultId) - const uniTokenId = vaultBefore?.NFTCollateralId + const uniTokenId = vaultBefore?.NFTCollateralId const position = uniTokenId ? await getPosition(uniTokenId) : null - if (!controllerContract || !controllerHelperContract || !address || !position || !vaultBefore || !squeethPoolContract) return + if ( + !controllerContract || + !controllerHelperContract || + !address || + !position || + !vaultBefore || + !squeethPoolContract + ) + return const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) const debtInEth = await getDebtAmount(shortAmount) const collateralToFlashloan = debtInEth.multipliedBy(COLLAT_RATIO_FLASHLOAN) // Get current LP positions - const { amount0, amount1 } = await getDecreaseLiquidity(uniTokenId, position.liquidity, 0, 0, Math.floor(Date.now() / 1000 + 86400)) - const amount0MinOld = new BigNumber(amount0).times(new BigNumber(1).minus(slippage)).toFixed(0) + const { amount0, amount1 } = await getDecreaseLiquidity( + uniTokenId, + position.liquidity, + 0, + 0, + Math.floor(Date.now() / 1000 + 86400), + ) + const amount0MinOld = new BigNumber(amount0).times(new BigNumber(1).minus(slippage)).toFixed(0) const amount1MinOld = new BigNumber(amount1).times(new BigNumber(1).minus(slippage)).toFixed(0) const wPowerPerpAmountInLPBefore = isWethToken0 ? amount1 : amount0 const wethAmountInLPBefore = isWethToken0 ? amount0 : amount1 @@ -284,13 +363,14 @@ export const useRebalanceGeneralSwap = () => { const upperTick = nearestUsableTick(upperTickInput, Number(tickSpacing)) const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(lowerTick).toString()).div(x96) const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(upperTick).toString()).div(x96) - const squeethPrice = isWethToken0 ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2)) - : new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2) + const squeethPrice = isWethToken0 + ? new BigNumber(1).div(new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2)) + : new BigNumber(TickMath.getSqrtRatioAtTick(Number(tick)).toString()).div(x96).pow(2) const sqrtSqueethPrice = squeethPrice.sqrt() // Get previous liquidity amount in ETH const wPowerPerpAmountInLPBeforeInEth = new BigNumber(wPowerPerpAmountInLPBefore).times(squeethPrice) - const positionEthValue = new BigNumber(wethAmountInLPBefore).plus(wPowerPerpAmountInLPBeforeInEth) + const positionEthValue = new BigNumber(wethAmountInLPBefore).plus(wPowerPerpAmountInLPBeforeInEth) let amountIn, wethAmountInLPAfter, wPowerPerpAmountInLPAfter, tokenIn, tokenOut if (sqrtUpperPrice.lt(sqrtSqueethPrice)) { @@ -306,31 +386,39 @@ export const useRebalanceGeneralSwap = () => { } else if (sqrtSqueethPrice.lt(sqrtLowerPrice)) { // All squeeth position // newLiquidity = positionEthValue/(squeethPrice/sqrt(lowerPrice) - squeethPrice/sqrt(upperPrice)) - const liquidity = positionEthValue.div((squeethPrice.div(sqrtLowerPrice)).minus((squeethPrice.div(sqrtUpperPrice)))) + const liquidity = positionEthValue.div(squeethPrice.div(sqrtLowerPrice).minus(squeethPrice.div(sqrtUpperPrice))) wethAmountInLPAfter = new BigNumber(0) // wPowerPerpAmount = L/sqrt(lowerPrice) - L/sqrt(upperPrice) - wPowerPerpAmountInLPAfter = (liquidity.div(sqrtLowerPrice).minus(liquidity.div(sqrtUpperPrice))) + wPowerPerpAmountInLPAfter = liquidity.div(sqrtLowerPrice).minus(liquidity.div(sqrtUpperPrice)) amountIn = wethAmountInLPBefore tokenIn = weth tokenOut = oSqueeth } else { // newLiquidity = positionEthValue/(squeethPrice/sqrt(squeethPrice) - squeethPrice/sqrt(upperPrice) + sqrt(squeethPrice) - sqrt(lowerPrice)) - const liquidity = positionEthValue.div((new BigNumber(squeethPrice).div(sqrtSqueethPrice)) - .minus((new BigNumber(squeethPrice).div(sqrtUpperPrice))) - .plus(sqrtSqueethPrice) - .minus(sqrtLowerPrice)) + const liquidity = positionEthValue.div( + new BigNumber(squeethPrice) + .div(sqrtSqueethPrice) + .minus(new BigNumber(squeethPrice).div(sqrtUpperPrice)) + .plus(sqrtSqueethPrice) + .minus(sqrtLowerPrice), + ) // Calculate amounts of each asset to LP // x = L(sqrt(upperPrice) - sqrt(squeethPrice))) / sqrt(squeethPrice) * sqrt(upperPrice) // y = L(sqrt(squeethPrice) - sqrt(lowerPrice)) - wPowerPerpAmountInLPAfter = liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div((sqrtSqueethPrice.times(sqrtUpperPrice))) + wPowerPerpAmountInLPAfter = liquidity + .times(sqrtUpperPrice.minus(sqrtSqueethPrice)) + .div(sqrtSqueethPrice.times(sqrtUpperPrice)) wethAmountInLPAfter = liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) const needMoreWeth = new BigNumber(wethAmountInLPBefore).lt(new BigNumber(wethAmountInLPAfter)) const needMoreSqueeth = new BigNumber(wPowerPerpAmountInLPBefore).lt(new BigNumber(wPowerPerpAmountInLPAfter)) tokenIn = needMoreWeth ? oSqueeth : weth tokenOut = needMoreWeth ? weth : oSqueeth - amountIn = needMoreWeth && !needMoreSqueeth ? new BigNumber(wPowerPerpAmountInLPBefore).minus(new BigNumber(wPowerPerpAmountInLPAfter)).toFixed(0) : - needMoreSqueeth && !needMoreWeth ? new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountInLPAfter)).toFixed(0) - : 0 + amountIn = + needMoreWeth && !needMoreSqueeth + ? new BigNumber(wPowerPerpAmountInLPBefore).minus(new BigNumber(wPowerPerpAmountInLPAfter)).toFixed(0) + : needMoreSqueeth && !needMoreWeth + ? new BigNumber(wethAmountInLPBefore).minus(new BigNumber(wethAmountInLPAfter)).toFixed(0) + : 0 } // Get amount mins @@ -350,13 +438,7 @@ export const useRebalanceGeneralSwap = () => { // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min] data: abiCoder.encode( ['uint256', 'uint256', 'uint256', 'uint128', 'uint128'], - [ - uniTokenId, - position.liquidity, - fromTokenAmount(1, 18).toFixed(0), - amount0MinOld, - amount1MinOld, - ], + [uniTokenId, position.liquidity, fromTokenAmount(1, 18).toFixed(0), amount0MinOld, amount1MinOld], ), } const generalSwap = { @@ -389,7 +471,8 @@ export const useRebalanceGeneralSwap = () => { ), } - const rebalanceLpInVaultParams = amountIn > 0 ? [liquidatePreviousLP, generalSwap, mintNewLP] : [liquidatePreviousLP, mintNewLP] + const rebalanceLpInVaultParams = + amountIn > 0 ? [liquidatePreviousLP, generalSwap, mintNewLP] : [liquidatePreviousLP, mintNewLP] return handleTransaction( await controllerHelperContract.methods @@ -400,7 +483,22 @@ export const useRebalanceGeneralSwap = () => { onTxConfirmed, ) }, - [address, controllerHelperContract, controllerHelper, weth, oSqueeth, squeethPool, controllerContract, handleTransaction, isWethToken0, getDebtAmount, getVault, getDecreaseLiquidity, getPosition, squeethPoolContract], + [ + address, + controllerHelperContract, + controllerHelper, + weth, + oSqueeth, + squeethPool, + controllerContract, + handleTransaction, + isWethToken0, + getDebtAmount, + getVault, + getDecreaseLiquidity, + getPosition, + squeethPoolContract, + ], ) return rebalanceGeneralSwap } @@ -408,104 +506,198 @@ export const useRebalanceGeneralSwap = () => { /*** GETTERS ***/ export const useGetPosition = () => { - const contract = useAtomValue(nftManagerContractAtom) - - const getPosition = useCallback( - async (uniTokenId: number) => { - if (!contract) return null - const position = await contract.methods.positions(uniTokenId).call() - const { nonce, operator, token0, token1, fee, tickLower, tickUpper, liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128, tokensOwed0, tokensOwed1 } = position - return { - nonce, - operator, - token0, - token1, - fee, - tickLower, - tickUpper, - liquidity, - feeGrowthInside0LastX128, - feeGrowthInside1LastX128, - tokensOwed0, - tokensOwed1 - } - }, - [contract], - ) - - return getPosition - } - - export const useGetDecreaseLiquidity = () => { - const contract = useAtomValue(nftManagerContractAtom) - - const getDecreaseLiquiduity = useCallback( - async (tokenId: number, liquidity: number, amount0Min: number, amount1Min: number, deadline: number) => { - if (!contract) return null - const DecreaseLiquidityParams = { - tokenId, - liquidity, - amount0Min, - amount1Min, - deadline, - } - - const decreaseLiquidity = await contract.methods.decreaseLiquidity(DecreaseLiquidityParams).call() - - return decreaseLiquidity - }, - [contract], - ) - - return getDecreaseLiquiduity - } - - export const useGetExactIn = () => { - const contract = useAtomValue(quoterContractAtom) - const {weth, oSqueeth} = useAtomValue(addressesAtom) - - const getExactIn = useCallback( - async (amount: BigNumber, squeethIn: boolean) => { - if (!contract) return null - - const QuoteExactInputSingleParams = { - tokenIn: squeethIn ? oSqueeth : weth, - tokenOut: squeethIn ? weth : oSqueeth, - amountIn: amount.toFixed(0), - fee: POOL_FEE, - sqrtPriceLimitX96: 0 - } - - const quote = await contract.methods.quoteExactInputSingle(QuoteExactInputSingleParams).call() - return quote.amountOut - }, - [contract, weth, oSqueeth], - ) - - return getExactIn - } - - export const useGetExactOut = () => { - const contract = useAtomValue(quoterContractAtom) - const {weth, oSqueeth} = useAtomValue(addressesAtom) - - const getExactOut = useCallback( - async (amount: BigNumber, squeethOut: boolean) => { - if (!contract) return null - - const QuoteExactOutputSingleParams = { - tokenIn: squeethOut ? weth : oSqueeth, - tokenOut: squeethOut ? oSqueeth : weth, - amount: amount.toFixed(0), - fee: POOL_FEE, - sqrtPriceLimitX96: 0 - } - - const quote = await contract.methods.quoteExactOutputSingle(QuoteExactOutputSingleParams).call() - return quote.amountIn - }, - [contract, weth, oSqueeth], - ) - - return getExactOut - } \ No newline at end of file + const contract = useAtomValue(nftManagerContractAtom) + + const getPosition = useCallback( + async (uniTokenId: number) => { + if (!contract) return null + const position = await contract.methods.positions(uniTokenId).call() + const { + nonce, + operator, + token0, + token1, + fee, + tickLower, + tickUpper, + liquidity, + feeGrowthInside0LastX128, + feeGrowthInside1LastX128, + tokensOwed0, + tokensOwed1, + } = position + return { + nonce, + operator, + token0, + token1, + fee, + tickLower, + tickUpper, + liquidity, + feeGrowthInside0LastX128, + feeGrowthInside1LastX128, + tokensOwed0, + tokensOwed1, + } + }, + [contract], + ) + + return getPosition +} + +export const useGetLiquidity = () => { + const isWethToken0 = useAtomValue(isWethToken0Atom) + + const getLiquidity = useCallback( + async ( + squeethAmount: BigNumber, + sqrtLowerPrice: BigNumber, + sqrtUpperPrice: BigNumber, + sqrtSqueethPrice: BigNumber, + ) => { + if (isWethToken0) { + // Ly = y / (sqrtSqueethPrice - sqrtLowerPrice) + console.log("checking liq", squeethAmount.div(sqrtSqueethPrice.minus(sqrtLowerPrice)).toString()) + return squeethAmount.div(sqrtSqueethPrice.minus(sqrtLowerPrice)) + } else { + // Lx = x * (sqrtSqueethPrice * sqrtUpperPrice) / (sqrtUpperPrice - sqrtSqueethPrice) + return squeethAmount.times(sqrtSqueethPrice.times(sqrtUpperPrice)).div(sqrtUpperPrice.minus(sqrtSqueethPrice)) + } + }, + [isWethToken0], + ) + + return getLiquidity +} + +export const useGetCollateralToLP = () => { + const isWethToken0 = useAtomValue(isWethToken0Atom) + const getLiquidity = useGetLiquidity() + const getTickPrices = useGetTickPrices() + + const getCollateralToLP = useCallback( + async ( + squeethAmount: BigNumber, + lowerTick: Number, + upperTick: Number, + tick: number, + ) => { + const { sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice } = await getTickPrices(lowerTick, upperTick, tick) + + if ((sqrtUpperPrice.lt(sqrtSqueethPrice) && !isWethToken0) || (sqrtLowerPrice.gt(sqrtSqueethPrice) && isWethToken0)) { + // All weth position + console.log('LPing an all WETH position is not enabled, but you can rebalance to this position.') + return + } else if ((sqrtLowerPrice.gt(sqrtSqueethPrice) && !isWethToken0) || (sqrtUpperPrice.lt(sqrtSqueethPrice) && isWethToken0)) { + // All squeeth position + return new BigNumber(0) + } else { + // isWethToken0 -> x = Ly * (sqrtUpperPrice - sqrtSqueethPrice)/(sqrtSqueethPrice * sqrtUpperPrice) + // !isWethToken0 -> y = Lx * (sqrtSqueethPrice - sqrtLowerPrice) + + const liquidity = await getLiquidity(squeethAmount, sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice) + console.log("liquidity", liquidity.toString()) + return isWethToken0 + ? liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div(sqrtSqueethPrice.times(sqrtUpperPrice)) + : liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) + } + }, + [isWethToken0, getLiquidity], + ) + + return getCollateralToLP +} + +export const useGetTickPrices = () => { + const getTickPrices = useCallback( + async (lowerTick: Number, upperTick: Number, currentTick: number) => { + const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(lowerTick)).toString()).div(x96) + const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(upperTick)).toString()).div(x96) + const sqrtSqueethPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(currentTick)).toString()).div(x96) + console.log("currentTick", currentTick.toString()) + console.log("lowerPrice", sqrtLowerPrice.pow(2).toString()) + console.log("upperPrice", sqrtUpperPrice.pow(2).toString()) + console.log("squeethPrice", sqrtSqueethPrice.pow(2).toString()) + return { sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice } + }, + [], + ) + + return getTickPrices +} + +export const useGetDecreaseLiquidity = () => { + const contract = useAtomValue(nftManagerContractAtom) + + const getDecreaseLiquiduity = useCallback( + async (tokenId: number, liquidity: number, amount0Min: number, amount1Min: number, deadline: number) => { + if (!contract) return null + const DecreaseLiquidityParams = { + tokenId, + liquidity, + amount0Min, + amount1Min, + deadline, + } + + const decreaseLiquidity = await contract.methods.decreaseLiquidity(DecreaseLiquidityParams).call() + + return decreaseLiquidity + }, + [contract], + ) + + return getDecreaseLiquiduity +} + +export const useGetExactIn = () => { + const contract = useAtomValue(quoterContractAtom) + const { weth, oSqueeth } = useAtomValue(addressesAtom) + + const getExactIn = useCallback( + async (amount: BigNumber, squeethIn: boolean) => { + if (!contract) return null + + const QuoteExactInputSingleParams = { + tokenIn: squeethIn ? oSqueeth : weth, + tokenOut: squeethIn ? weth : oSqueeth, + amountIn: amount.toFixed(0), + fee: POOL_FEE, + sqrtPriceLimitX96: 0, + } + + const quote = await contract.methods.quoteExactInputSingle(QuoteExactInputSingleParams).call() + return quote.amountOut + }, + [contract, weth, oSqueeth], + ) + + return getExactIn +} + +export const useGetExactOut = () => { + const contract = useAtomValue(quoterContractAtom) + const { weth, oSqueeth } = useAtomValue(addressesAtom) + + const getExactOut = useCallback( + async (amount: BigNumber, squeethOut: boolean) => { + if (!contract) return null + + const QuoteExactOutputSingleParams = { + tokenIn: squeethOut ? weth : oSqueeth, + tokenOut: squeethOut ? oSqueeth : weth, + amount: amount.toFixed(0), + fee: POOL_FEE, + sqrtPriceLimitX96: 0, + } + + const quote = await contract.methods.quoteExactOutputSingle(QuoteExactOutputSingleParams).call() + return quote.amountIn + }, + [contract, weth, oSqueeth], + ) + + return getExactOut +} From 69439af49537710c1d325bc4dcc8a60c9b737b1c Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Thu, 25 Aug 2022 10:21:49 -0700 Subject: [PATCH 80/82] fix flashloan --- packages/frontend/src/state/lp/hooks.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 51c46929e..f06729775 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -95,7 +95,7 @@ export const useOpenPositionDeposit = () => { .times(normFactor) .times(ethIndexPrice) .div(INDEX_SCALE) - .minus(vaultCollateralAmt.plus(collateralToMint).minus(collateralToWithdraw)) + .minus(vaultCollateralAmt) const collateralToMintPos = BigNumber.max(collateralToMint, 0) const flashLoanAmountPos = BigNumber.max(flashLoanAmount, 0) From 4e27f4cb19d3bdc26f5855cdd5a2e9e0686a9b75 Mon Sep 17 00:00:00 2001 From: Darya Kaviani Date: Sun, 28 Aug 2022 22:32:30 -0700 Subject: [PATCH 81/82] close tweaks --- packages/frontend/pages/lp.tsx | 4 +- packages/frontend/src/state/lp/hooks.ts | 87 ++++++++++++++----------- 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index 306f913be..f185bf23d 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -15,7 +15,7 @@ import { SqueethTab, SqueethTabs } from '@components/Tabs' import { useETHPrice } from '@hooks/useETHPrice' import { supportedNetworkAtom } from 'src/state/wallet/atoms' import { useAtomValue } from 'jotai' -import { useClosePosition, useOpenPositionDeposit, useRebalanceGeneralSwap } from 'src/state/lp/hooks' +import { useFlashClosePosition, useOpenPositionDeposit, useRebalanceGeneralSwap } from 'src/state/lp/hooks' import { useCollectFees } from 'src/state/lp/hooks' import BigNumber from 'bignumber.js' import useAppCallback from '@hooks/useAppCallback' @@ -103,7 +103,7 @@ export function LPCalculator() { const supportedNetwork = useAtomValue(supportedNetworkAtom) const squeethPrice = useGetTwapSqueethPrice() const openLPPosition = useOpenPositionDeposit() - const closeLPPosition = useClosePosition() + const closeLPPosition = useFlashClosePosition() const collectFees = useCollectFees() const rebalanceSwap = useRebalanceGeneralSwap() const updateOperator = useUpdateOperator() diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index f06729775..56326baeb 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -69,19 +69,17 @@ export const useOpenPositionDeposit = () => { const { tick, tickSpacing } = await getPoolState(squeethPoolContract) const lowerTick = nearestUsableTick(lowerTickInput, Number(tickSpacing)) const upperTick = nearestUsableTick(upperTickInput, Number(tickSpacing)) - console.log("upperTick", upperTick) const collateralToLp = await getCollateralToLP(mintWSqueethAmount, lowerTick, upperTick, tick) if (!collateralToLp) return - console.log("collateralToLp", collateralToLp.toString()) - + const amount0New = isWethToken0 ? collateralToLp : mintWSqueethAmount const amount1New = isWethToken0 ? mintWSqueethAmount : collateralToLp const amount0Min = amount0New.times(new BigNumber(1).minus(slippage)).toFixed(0) const amount1Min = amount1New.times(new BigNumber(1).minus(slippage)).toFixed(0) - const collateralToWithdraw = fromTokenAmount(withdrawAmount, OSQUEETH_DECIMALS) - const ethIndexPrice = toTokenAmount(index, 18).sqrt() + const collateralToWithdraw = fromTokenAmount(withdrawAmount, WETH_DECIMALS) + const ethIndexPrice = toTokenAmount(index, WETH_DECIMALS).sqrt() const vaultShortAmt = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS) @@ -139,7 +137,7 @@ export const useOpenPositionDeposit = () => { } // Close position with flashloan -export const useClosePosition = () => { +export const useFlashClosePosition = () => { const address = useAtomValue(addressAtom) const controllerHelperContract = useAtomValue(controllerHelperHelperContractAtom) const controllerContract = useAtomValue(controllerContractAtom) @@ -151,12 +149,14 @@ export const useClosePosition = () => { const getExactOut = useGetExactOut() const getDecreaseLiquidity = useGetDecreaseLiquidity() const isWethToken0 = useAtomValue(isWethToken0Atom) - const closePosition = useAppCallback( + const index = useAtomValue(indexAtom) + const normFactor = useAtomValue(normFactorAtom) + const flashClosePosition = useAppCallback( async ( vaultId: number, liquidityPercentage: number, burnPercentage: number, - collateralToWithdraw: number, + withdrawAmount: number, burnExactRemoved: boolean, slippage: number, onTxConfirmed?: () => void, @@ -176,7 +176,6 @@ export const useClosePosition = () => { return const shortAmount = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) - const debtInEthPromise = getDebtAmount(shortAmount) // Get current LP positions const { amount0, amount1 } = await getDecreaseLiquidity( @@ -190,17 +189,27 @@ export const useClosePosition = () => { const amountToLiquidate = new BigNumber(wPowerPerpAmountInLP).times(liquidityPercentage) const amountToBurn = shortAmount.times(burnPercentage) - const limitEthPromise = amountToLiquidate.gt(amountToBurn) + const limitEth = await (amountToLiquidate.gt(amountToBurn) ? getExactIn(amountToLiquidate.minus(amountToBurn), true) - : getExactOut(amountToBurn.minus(amountToLiquidate), true) + : getExactOut(amountToBurn.minus(amountToLiquidate), true)) + + const collateralToWithdraw = fromTokenAmount(withdrawAmount, WETH_DECIMALS) + const ethIndexPrice = toTokenAmount(index, WETH_DECIMALS).sqrt() + const vaultShortAmt = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) + const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS) + + const flashLoanAmount = new BigNumber(COLLAT_RATIO_FLASHLOAN + FLASHLOAN_BUFFER) + .times(vaultShortAmt) + .times(normFactor) + .times(ethIndexPrice) + .div(INDEX_SCALE) + .minus(vaultCollateralAmt) + const flashLoanAmountPos = BigNumber.max(flashLoanAmount, 0) - const [debtInEth, limitEth] = await Promise.all([debtInEthPromise, limitEthPromise]) const limitPrice = new BigNumber(limitEth) .div(amountToLiquidate.minus(amountToBurn).abs()) .times(new BigNumber(1).minus(slippage)) - const collateralToFlashloan = debtInEth.multipliedBy(COLLAT_RATIO_FLASHLOAN) - const amount0Min = new BigNumber(amount0) .times(liquidityPercentage) .times(new BigNumber(1).minus(slippage)) @@ -216,7 +225,7 @@ export const useClosePosition = () => { liquidity: position.liquidity, liquidityPercentage: fromTokenAmount(liquidityPercentage, 18).toFixed(0), wPowerPerpAmountToBurn: amountToBurn.toFixed(0), - collateralToFlashloan: collateralToFlashloan.toFixed(0), + collateralToFlashloan: flashLoanAmountPos.toFixed(0), collateralToWithdraw: collateralToWithdraw.toFixed(0), limitPriceEthPerPowerPerp: fromTokenAmount(limitPrice, 18).toFixed(0), amount0Min, @@ -244,9 +253,11 @@ export const useClosePosition = () => { getExactOut, getDecreaseLiquidity, isWethToken0, + index, + normFactor, ], ) - return closePosition + return flashClosePosition } // Collect fees @@ -559,7 +570,7 @@ export const useGetLiquidity = () => { ) => { if (isWethToken0) { // Ly = y / (sqrtSqueethPrice - sqrtLowerPrice) - console.log("checking liq", squeethAmount.div(sqrtSqueethPrice.minus(sqrtLowerPrice)).toString()) + console.log('checking liq', squeethAmount.div(sqrtSqueethPrice.minus(sqrtLowerPrice)).toString()) return squeethAmount.div(sqrtSqueethPrice.minus(sqrtLowerPrice)) } else { // Lx = x * (sqrtSqueethPrice * sqrtUpperPrice) / (sqrtUpperPrice - sqrtSqueethPrice) @@ -578,19 +589,20 @@ export const useGetCollateralToLP = () => { const getTickPrices = useGetTickPrices() const getCollateralToLP = useCallback( - async ( - squeethAmount: BigNumber, - lowerTick: Number, - upperTick: Number, - tick: number, - ) => { + async (squeethAmount: BigNumber, lowerTick: Number, upperTick: Number, tick: number) => { const { sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice } = await getTickPrices(lowerTick, upperTick, tick) - if ((sqrtUpperPrice.lt(sqrtSqueethPrice) && !isWethToken0) || (sqrtLowerPrice.gt(sqrtSqueethPrice) && isWethToken0)) { + if ( + (sqrtUpperPrice.lt(sqrtSqueethPrice) && !isWethToken0) || + (sqrtLowerPrice.gt(sqrtSqueethPrice) && isWethToken0) + ) { // All weth position console.log('LPing an all WETH position is not enabled, but you can rebalance to this position.') return - } else if ((sqrtLowerPrice.gt(sqrtSqueethPrice) && !isWethToken0) || (sqrtUpperPrice.lt(sqrtSqueethPrice) && isWethToken0)) { + } else if ( + (sqrtLowerPrice.gt(sqrtSqueethPrice) && !isWethToken0) || + (sqrtUpperPrice.lt(sqrtSqueethPrice) && isWethToken0) + ) { // All squeeth position return new BigNumber(0) } else { @@ -598,7 +610,7 @@ export const useGetCollateralToLP = () => { // !isWethToken0 -> y = Lx * (sqrtSqueethPrice - sqrtLowerPrice) const liquidity = await getLiquidity(squeethAmount, sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice) - console.log("liquidity", liquidity.toString()) + console.log('liquidity', liquidity.toString()) return isWethToken0 ? liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div(sqrtSqueethPrice.times(sqrtUpperPrice)) : liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice)) @@ -611,19 +623,16 @@ export const useGetCollateralToLP = () => { } export const useGetTickPrices = () => { - const getTickPrices = useCallback( - async (lowerTick: Number, upperTick: Number, currentTick: number) => { - const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(lowerTick)).toString()).div(x96) - const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(upperTick)).toString()).div(x96) - const sqrtSqueethPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(currentTick)).toString()).div(x96) - console.log("currentTick", currentTick.toString()) - console.log("lowerPrice", sqrtLowerPrice.pow(2).toString()) - console.log("upperPrice", sqrtUpperPrice.pow(2).toString()) - console.log("squeethPrice", sqrtSqueethPrice.pow(2).toString()) - return { sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice } - }, - [], - ) + const getTickPrices = useCallback(async (lowerTick: Number, upperTick: Number, currentTick: number) => { + const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(lowerTick)).toString()).div(x96) + const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(upperTick)).toString()).div(x96) + const sqrtSqueethPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(currentTick)).toString()).div(x96) + console.log('currentTick', currentTick.toString()) + console.log('lowerPrice', sqrtLowerPrice.pow(2).toString()) + console.log('upperPrice', sqrtUpperPrice.pow(2).toString()) + console.log('squeethPrice', sqrtSqueethPrice.pow(2).toString()) + return { sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice } + }, []) return getTickPrices } From 11b35eb192b63b656779383b9a0b6520014098db Mon Sep 17 00:00:00 2001 From: nikhil arora Date: Sat, 19 Nov 2022 00:14:27 +0530 Subject: [PATCH 82/82] chore: make it ready for goerli --- packages/frontend/src/constants/address.ts | 27 ++++++++++++++++++++++ packages/frontend/src/state/lp/hooks.ts | 6 +++-- packages/frontend/src/types/index.ts | 1 + 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/constants/address.ts b/packages/frontend/src/constants/address.ts index e72239ca1..661428871 100644 --- a/packages/frontend/src/constants/address.ts +++ b/packages/frontend/src/constants/address.ts @@ -5,6 +5,7 @@ type Address = { [key in Networks]: string } export const CONTROLLER: Address = { 1: '0x64187ae08781B09368e6253F9E94951243A493D5', 3: '0x59F0c781a6eC387F09C40FAA22b7477a2950d209', + 5: '0x2c60f986260c8412De7fA3384C7f0Bab1a4F72bf', 421611: '0x6FBbc7eBd7E421839915e8e4fAcC9947dC32F4dE', 31337: '0xa513E6E4b8f2a923D98304ec87F64353C4D5C853', } @@ -13,6 +14,7 @@ export const CONTROLLER: Address = { export const VAULT_MANAGER: Address = { 1: '0xa653e22A963ff0026292Cc8B67941c0ba7863a38', 3: '0x49721ED2d693F3653BC1216b8E330fA53CFC80eD', + 5: '0x66a6a5bCF0cc97b317779152A8a8765FE3802E7C', 421611: '0x40FA4273a739667D7dBf1C46755C27338eAa0728', 31337: '0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6', } @@ -21,6 +23,7 @@ export const VAULT_MANAGER: Address = { export const OSQUEETH: Address = { 1: '0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B', 3: '0xa4222f78d23593e82Aa74742d25D06720DCa4ab7', + 5: '0x6b03eD2C590A301E79E2DCe4ce38D7402dC6735a', 421611: '0xEC0db8766bc003C14861af996e411beA6Bf800aB', 31337: '0x8A791620dd6260079BF849Dc5567aDC3F2FdC318', } @@ -28,6 +31,7 @@ export const OSQUEETH: Address = { export const WETH: Address = { 1: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', 3: '0xc778417e063141139fce010982780140aa0cd5ab', + 5: '0x0719E63EC564259D1ce12dFFD1431269C7d88700', 421611: '0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681', 31337: '0x5FbDB2315678afecb367f032d93F642f64180aa3', } @@ -35,6 +39,7 @@ export const WETH: Address = { export const USDC: Address = { 1: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', 3: '0x27415c30d8c87437becbd4f98474f26e712047f4', + 5: '0x12F263aAB668aF8918E077af3a9CF5da9fE9A417', 421611: '0xc4D15025D49a88D70B023870d810f4cAa5c18a63', 31337: '0x8dF057949E6717B6f28962f30e8415b148241e16', } @@ -42,6 +47,7 @@ export const USDC: Address = { export const UNI_V3_FACTORY: Address = { 1: '0x1F98431c8aD98523631AE4a59f267346ea31F984', 3: '0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc', + 5: '0x2Db05f50645a7EAEd686bdf64DE3F90Fde2041b3', 421611: '0x1F98431c8aD98523631AE4a59f267346ea31F984', 31337: '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512', } @@ -49,13 +55,16 @@ export const UNI_V3_FACTORY: Address = { export const SWAP_ROUTER: Address = { 1: '0xE592427A0AEce92De3Edee1F18E0157C05861564', 3: '0x528a19A3e88861E7298C86fE5490B8Ec007a4204', + 5: '0x200775Be10EA5dCee478C193E6B6E66E13d878C0', 421611: '0xE592427A0AEce92De3Edee1F18E0157C05861564', 31337: '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9', } +// check this one! export const SWAP_ROUTER_02: Address = { 1: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45', 3: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45', + 5: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45', 421611: '', 31337: '', } @@ -63,6 +72,7 @@ export const SWAP_ROUTER_02: Address = { export const SQUEETH_UNI_POOL: Address = { 1: '0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C', 3: '0x921c384F79de1BAe96d6f33E3E5b8d0B2B34cb68', + 5: '0xB583EA07699c5DEa4da084056273d6D70c2C3309', 421611: '0x0567A9C01990a4C7EE096F077A05CeEbA87db07f', 31337: '0x8dF057949E6717B6f28962f30e8415b148241e16', } @@ -70,6 +80,7 @@ export const SQUEETH_UNI_POOL: Address = { export const QUOTER: Address = { 1: '0xC8d3a4e6BB4952E3658CCA5081c358e6935Efa43', 3: '0x267aEB76BEb6DC7Ab0D88FeEaC8A948e237e2d69', + 5: '0x5D9D69aF49130fEb2511fdFc1A55B5746897BdE4', 421611: '0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D', 31337: '0x5FC8d32690cc91D4c39d9d3abcBD16989F875707', } @@ -77,6 +88,7 @@ export const QUOTER: Address = { export const SHORT_HELPER: Address = { 1: '0x3b4095D5ff0e629972CAAa50bd3004B09a1632C5', 3: '0x8903918DFE74476E90B63061E5b9c3E63b65d3F4', + 5: '0x03F4a45341B46eDEb7542890e4bEa94868CB679e', 421611: '0x5A30a1E3873A2B5Fc9DB9b2b52491C4b6086FAe0', 31337: '0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE', } @@ -84,6 +96,7 @@ export const SHORT_HELPER: Address = { export const ORACLE: Address = { 1: '0x65D66c76447ccB45dAf1e8044e918fA786A483A1', 3: '0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89', + 5: '0x3A1B8e5D405F4080442C878aA114B17a1D60E14B', 421611: '0xe790Afe86c0bdc4Dd7C6CBb7dB087552Ec85F6fB', 31337: '0x0165878A594ca255338adfa4d48449f69242Eb8F', } @@ -91,6 +104,7 @@ export const ORACLE: Address = { export const ETH_USDC_POOL: Address = { 1: '0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8', 3: '0x8356AbC730a218c24446C2c85708F373f354F0D8', + 5: '0x8875e9c9EB0909da889CB3Dc9c5E8856093CE6b0', 421611: '0xe7715b01a0B16E3e38A7d9b78F6Bd2b163D7f319', 31337: '0x8dF057949E6717B6f28962f30e8415b148241e16', } @@ -98,6 +112,7 @@ export const ETH_USDC_POOL: Address = { export const NFT_MANAGER: Address = { 1: '0xC36442b4a4522E871399CD717aBDD847Ab11FE88', 3: '0x8c7c1f786da4dee7d4bb49697a9b0c0c8fb328e0', + 5: '0xa22acAd8494B641D374f510CD88DeacABe24B0F9', 421611: '', 31337: '', } @@ -105,6 +120,7 @@ export const NFT_MANAGER: Address = { export const CRAB_STRATEGY: Address = { 1: '0xf205ad80bb86ac92247638914265887a8baa437d', 3: '0xbffBD99cFD9d77c49595dFe8eB531715906ca4Cf', + 5: '0x74b9e08b801b0df247A14c0f91E7143ea95C946B', 421611: '', 31337: '', } @@ -112,6 +128,7 @@ export const CRAB_STRATEGY: Address = { export const CRAB_MIGRATION: Address = { 1: '0xa1cab67a4383312718a5799eaa127906e9d4b19e', 3: '0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f', + 5: '0x5632367328327189A4858ac413A6424fe12F6C8f', // this is a wrong address, ignore for now 421611: '', 31337: '', } @@ -119,6 +136,7 @@ export const CRAB_MIGRATION: Address = { export const CRAB_STRATEGY2: Address = { 1: '0x3B960E47784150F5a63777201ee2B15253D713e8', 3: '0xdD1e9c25115e0d6e531d9F9E6ab7dbbEd15158Ce', + 5: '0x49a423Bc9F1dEe5A052b1E72a1dbE9de488d4411', 421611: '', 31337: '', } @@ -128,6 +146,15 @@ export const ZERO_ADDR = '0x0000000000000000000000000000000000000000' export const CONTROLLER_HELPER: Address = { 1: '0xfa86d43b41Fa7a759c606130cc81970A955ff816', 3: '0x7e9C5490e91F93529c6480B46a59D738F6bcEa43', + 5: '0x50f3D0826d4E3c3d49007DBa664727B9885Dd734', // this one is wrong too + 421611: '', + 31337: '', +} + +export const CRAB_HELPER: Address = { + 1: '0x2f55e27e669f070def7b5771db72f6b31a6d4df8', + 3: '', + 5: '0x660BA6A7EedbF18CC3041cE3B1223385298e3275', 421611: '', 31337: '', } diff --git a/packages/frontend/src/state/lp/hooks.ts b/packages/frontend/src/state/lp/hooks.ts index 56326baeb..72431dfd6 100644 --- a/packages/frontend/src/state/lp/hooks.ts +++ b/packages/frontend/src/state/lp/hooks.ts @@ -111,6 +111,8 @@ export const useOpenPositionDeposit = () => { upperTick: upperTick, } + console.log(JSON.stringify(flashloanWMintDepositNftParams, undefined, 2)) + return handleTransaction( contract.methods.flashloanWMintLpDepositNft(flashloanWMintDepositNftParams).send({ from: address, @@ -196,8 +198,8 @@ export const useFlashClosePosition = () => { const collateralToWithdraw = fromTokenAmount(withdrawAmount, WETH_DECIMALS) const ethIndexPrice = toTokenAmount(index, WETH_DECIMALS).sqrt() const vaultShortAmt = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS) - const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS) - + const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS) + const flashLoanAmount = new BigNumber(COLLAT_RATIO_FLASHLOAN + FLASHLOAN_BUFFER) .times(vaultShortAmt) .times(normFactor) diff --git a/packages/frontend/src/types/index.ts b/packages/frontend/src/types/index.ts index c37645204..44c6d1e79 100644 --- a/packages/frontend/src/types/index.ts +++ b/packages/frontend/src/types/index.ts @@ -26,6 +26,7 @@ declare module '@material-ui/core/Typography' { export enum Networks { MAINNET = 1, ROPSTEN = 3, + GOERLI = 5, ARBITRUM_RINKEBY = 421611, LOCAL = 31337, }