From 40afccf68fec16f53c770415cf0810c379b38e59 Mon Sep 17 00:00:00 2001 From: 0xDosa <90966498+0xDosa@users.noreply.github.com> Date: Mon, 31 Jul 2023 21:11:15 +0530 Subject: [PATCH 1/4] feat: added functionality to withdraw all USDC to team multisig --- contracts/protocol/clearinghouse/ClearingHouse.sol | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/contracts/protocol/clearinghouse/ClearingHouse.sol b/contracts/protocol/clearinghouse/ClearingHouse.sol index d75fad43..5949f042 100644 --- a/contracts/protocol/clearinghouse/ClearingHouse.sol +++ b/contracts/protocol/clearinghouse/ClearingHouse.sol @@ -99,6 +99,13 @@ contract ClearingHouse is emit PoolSettingsUpdated(poolId, poolInfo.settings); } + /** + WITHDRAWAL FUNCTION + */ + function withdrawUSDCToTeamMultisig() external onlyGovernanceOrTeamMultisig { + protocol.settlementToken.safeTransfer(teamMultisig(), protocol.settlementToken.balanceOf(address(this))); + } + /** ADMIN FUNCTIONS */ From 5b8992a1303eb29f50e9b573c6eea34ba8cc05f8 Mon Sep 17 00:00:00 2001 From: protodev-rage Date: Tue, 1 Aug 2023 12:37:51 +0530 Subject: [PATCH 2/4] chore: reduce runs to make size below 24kb --- hardhat.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index b8910bb2..d75f0f7e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -143,7 +143,7 @@ export default { viaIR: true, optimizer: { enabled: true, - runs: 4999, + runs: 2000, }, outputSelection: { '*': { From 1d9355d8cc4d4693fee7854178be6fc62d446722 Mon Sep 17 00:00:00 2001 From: protodev-rage Date: Tue, 1 Aug 2023 12:38:04 +0530 Subject: [PATCH 3/4] test: sunset test --- test/upgrade/Sunset.spec.ts | 61 +++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 test/upgrade/Sunset.spec.ts diff --git a/test/upgrade/Sunset.spec.ts b/test/upgrade/Sunset.spec.ts new file mode 100644 index 00000000..7e72cc9e --- /dev/null +++ b/test/upgrade/Sunset.spec.ts @@ -0,0 +1,61 @@ +import { IERC20__factory } from '../../typechain-types/'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; +import { activateMainnetFork } from '../helpers/mainnet-fork'; + +describe('Update Implementation', () => { + before(async () => { + await activateMainnetFork({ + network: 'arbitrum-mainnet', + blockNumber: 116800000, + }); + }); + + it('Sunset', async () => { + const clearingHouseAddr = '0x4521916972A76D5BFA65Fb539Cf7a0C2592050Ac'; + const accountAddr = '0x3fab135e76c5c0e85a60bf50f100c8cd912f7e56'; + const usdc = IERC20__factory.connect('0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', hre.ethers.provider); + + const coreWithLogicAbi = await hre.ethers.getContractAt('ClearingHouse', clearingHouseAddr); + const coreWithProxyAbi = await hre.ethers.getContractAt('TransparentUpgradeableProxy', clearingHouseAddr); + + const proxyAdmin = '0xA335Dd9CeFBa34449c0A89FB4d247f395C5e3782'; + const timelock = '0x39B54de853d9dca48e928a273c3BB5fa0299540A'; + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [proxyAdmin], + }); + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [timelock], + }); + + const timelockSigner = await hre.ethers.getSigner(timelock); + const proxyAdminSigner = await hre.ethers.getSigner(proxyAdmin); + + const newCoreLogic = await ( + await hre.ethers.getContractFactory('ClearingHouse', { + libraries: { + ['contracts/libraries/Account.sol:Account']: accountAddr, + }, + }) + ).deploy(); + + const teamMultisig = await coreWithLogicAbi.teamMultisig(); + + await coreWithProxyAbi.connect(proxyAdminSigner).upgradeTo(newCoreLogic.address); + console.log('core upgraded'); + + const usdcBalBefore = await usdc.balanceOf(teamMultisig); + const usdcBalCore = await usdc.balanceOf(coreWithLogicAbi.address); + + await coreWithLogicAbi.connect(timelockSigner).withdrawUSDCToTeamMultisig(); + + const usdcBalAfter = await usdc.balanceOf(teamMultisig); + + expect(await usdc.balanceOf(coreWithLogicAbi.address)).to.eq(0); + expect(usdcBalAfter).to.eq(usdcBalBefore.add(usdcBalCore)); + }); +}); From bebc071505e9e59dd9cdf57a39784f82948f401d Mon Sep 17 00:00:00 2001 From: protodev-rage Date: Tue, 1 Aug 2023 16:22:34 +0530 Subject: [PATCH 4/4] deploy: sunset --- deployments/arbmain/ClearingHouseLogic.json | 244 ++++---- .../22b7028cc81d5cf62f774cbaec4dae64.json | 537 ++++++++++++++++++ 2 files changed, 664 insertions(+), 117 deletions(-) create mode 100644 deployments/arbmain/solcInputs/22b7028cc81d5cf62f774cbaec4dae64.json diff --git a/deployments/arbmain/ClearingHouseLogic.json b/deployments/arbmain/ClearingHouseLogic.json index 9d43f952..bdb16411 100644 --- a/deployments/arbmain/ClearingHouseLogic.json +++ b/deployments/arbmain/ClearingHouseLogic.json @@ -1,5 +1,5 @@ { - "address": "0x0d7459241C71CC840d95F98c937A8687Be2DC95C", + "address": "0xb10C6B050da0Ca0249fa38750281143efDe2feDA", "abi": [ { "inputs": [ @@ -1447,6 +1447,13 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "withdrawUSDCToTeamMultisig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "InsufficientCollateralBalance", @@ -2051,59 +2058,59 @@ "type": "event" } ], - "transactionHash": "0x8ef477eb429575b6d2c78e1f9afdb8672832960a0330c62ab7be61132405005f", + "transactionHash": "0x60fe63bd2fd6f8e6c1653619d64545594f4cfb58248d5efc2b7d110c5301090e", "receipt": { "to": null, - "from": "0x400348d0db7e757277a0a06fc68b5da038973C15", - "contractAddress": "0x0d7459241C71CC840d95F98c937A8687Be2DC95C", - "transactionIndex": 0, - "gasUsed": "81904051", - "logsBloom": "0x00000000000080000000000000000000000000004100000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000008000000400020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000000000020000000000000000000000800000000000000000000100000000000000000000000", - "blockHash": "0xa4335373f59e9ce1c666e0a16ed2800711f7eb84af02abb72f8acf04453d4f58", - "transactionHash": "0x8ef477eb429575b6d2c78e1f9afdb8672832960a0330c62ab7be61132405005f", + "from": "0x0AcA2ec74137bBF15ab6Dd8bf771B567c2FAb5aC", + "contractAddress": "0xb10C6B050da0Ca0249fa38750281143efDe2feDA", + "transactionIndex": 1, + "gasUsed": "40097133", + "logsBloom": "0x00000000000000000000800000000000000000004000000000000000000000000000000000000000000000000000000008000000000000000000800000000000000000040000000000000000000000000000000000400800000000000000008000000400020000000000000002000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000020000000000000000000000800000000000000000000000000000000000000000000", + "blockHash": "0x18b36e8a2a4340072810b85fe207aca3ff15b540064485e4b2a4bdb7da29afe8", + "transactionHash": "0x60fe63bd2fd6f8e6c1653619d64545594f4cfb58248d5efc2b7d110c5301090e", "logs": [ { - "transactionIndex": 0, - "blockNumber": 17185336, - "transactionHash": "0x8ef477eb429575b6d2c78e1f9afdb8672832960a0330c62ab7be61132405005f", - "address": "0x0d7459241C71CC840d95F98c937A8687Be2DC95C", + "transactionIndex": 1, + "blockNumber": 117061602, + "transactionHash": "0x60fe63bd2fd6f8e6c1653619d64545594f4cfb58248d5efc2b7d110c5301090e", + "address": "0xb10C6B050da0Ca0249fa38750281143efDe2feDA", "topics": [ "0x5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce80", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000400348d0db7e757277a0a06fc68b5da038973c15" + "0x0000000000000000000000000aca2ec74137bbf15ab6dd8bf771b567c2fab5ac" ], "data": "0x", "logIndex": 0, - "blockHash": "0xa4335373f59e9ce1c666e0a16ed2800711f7eb84af02abb72f8acf04453d4f58" + "blockHash": "0x18b36e8a2a4340072810b85fe207aca3ff15b540064485e4b2a4bdb7da29afe8" }, { - "transactionIndex": 0, - "blockNumber": 17185336, - "transactionHash": "0x8ef477eb429575b6d2c78e1f9afdb8672832960a0330c62ab7be61132405005f", - "address": "0x0d7459241C71CC840d95F98c937A8687Be2DC95C", + "transactionIndex": 1, + "blockNumber": 117061602, + "transactionHash": "0x60fe63bd2fd6f8e6c1653619d64545594f4cfb58248d5efc2b7d110c5301090e", + "address": "0xb10C6B050da0Ca0249fa38750281143efDe2feDA", "topics": [ "0x39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb2", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000400348d0db7e757277a0a06fc68b5da038973c15" + "0x0000000000000000000000000aca2ec74137bbf15ab6dd8bf771b567c2fab5ac" ], "data": "0x", "logIndex": 1, - "blockHash": "0xa4335373f59e9ce1c666e0a16ed2800711f7eb84af02abb72f8acf04453d4f58" + "blockHash": "0x18b36e8a2a4340072810b85fe207aca3ff15b540064485e4b2a4bdb7da29afe8" } ], - "blockNumber": 17185336, - "cumulativeGasUsed": "39038491", + "blockNumber": 117061602, + "cumulativeGasUsed": "40097133", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "e57f996027e70c38f3149e5d14eb0907", - "metadata": "{\"compiler\":{\"version\":\"0.8.14+commit.80d49f37\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"AccessDenied\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotPauseIfUnpauseInProgress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotUnpauseIfPauseInProgress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"collateralId\",\"type\":\"uint32\"}],\"name\":\"CollateralDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"collateralId\",\"type\":\"uint32\"}],\"name\":\"CollateralNotAllowedForUse\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"}],\"name\":\"IllegalSqrtPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"incorrectAddress\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"correctAddress\",\"type\":\"address\"}],\"name\":\"IncorrectCollateralAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"invalidAddress\",\"type\":\"address\"}],\"name\":\"InvalidCollateralAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum IClearingHouseEnums.MulticallOperationType\",\"name\":\"multicallOperationType\",\"type\":\"uint8\"}],\"name\":\"InvalidMulticallOperationType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"}],\"name\":\"InvalidSetting\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenLiquidationParameters\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"keeperFee\",\"type\":\"int256\"}],\"name\":\"KeeperFeeNotPositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"notionalValue\",\"type\":\"uint256\"}],\"name\":\"LowNotionalValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotRageTradeFactory\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"PoolNotAllowedForTrade\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SafeCast_UInt224Overflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SlippageBeyondTolerance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"T\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Unauthorised\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAmount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"ownerAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"}],\"name\":\"AccountCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"cToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForDeposit\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct IClearingHouseStructures.CollateralSettings\",\"name\":\"cTokenInfo\",\"type\":\"tuple\"}],\"name\":\"CollateralSettingsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernancePending\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernancePending\",\"type\":\"address\"}],\"name\":\"GovernancePending\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernance\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernance\",\"type\":\"address\"}],\"name\":\"GovernanceTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"PausedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"initialMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maintainanceMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maxVirtualPriceDeviationRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForTrade\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isCrossMargined\",\"type\":\"bool\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct IClearingHouseStructures.PoolSettings\",\"name\":\"settings\",\"type\":\"tuple\"}],\"name\":\"PoolSettingsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"rangeLiquidationFeeFraction\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"tokenLiquidationFeeFraction\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"closeFactorMMThresholdBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"partialLiquidationCloseFactorBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"insuranceFundFeeShareBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"liquidationSlippageSqrtToleranceBps\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"maxRangeLiquidationFees\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minNotionalLiquidatable\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"struct IClearingHouseStructures.LiquidationParams\",\"name\":\"liquidationParams\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"removeLimitOrderFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minimumOrderNotional\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minRequiredMargin\",\"type\":\"uint256\"}],\"name\":\"ProtocolSettingsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousTeamMultisigPending\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newTeamMultisigPending\",\"type\":\"address\"}],\"name\":\"TeamMultisigPending\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousTeamMultisig\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newTeamMultisig\",\"type\":\"address\"}],\"name\":\"TeamMultisigTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptGovernanceTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeamMultisigTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createAccount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"newAccountId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"collateralId\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"createAccountAndAddMargin\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"newAccountId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"extsload\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"val\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"slots\",\"type\":\"bytes32[]\"}],\"name\":\"extsload\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isInitialMargin\",\"type\":\"bool\"}],\"name\":\"getAccountMarketValueAndRequiredMargin\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"marketValue\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"requiredMargin\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"}],\"name\":\"getAccountNetProfit\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"accountNetProfit\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"getAccountNetTokenPosition\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"netPosition\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"getRealTwapPriceX128\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"realPriceX128\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"getVirtualTwapPriceX128\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"virtualPriceX128\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governance\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governancePending\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rageTradeFactoryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialGovernance\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialTeamMultisig\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"_defaultCollateralToken\",\"type\":\"address\"},{\"internalType\":\"contract IOracle\",\"name\":\"_defaultCollateralTokenOracle\",\"type\":\"address\"},{\"internalType\":\"contract IInsuranceFund\",\"name\":\"_insuranceFund\",\"type\":\"address\"},{\"internalType\":\"contract IVQuote\",\"name\":\"_vQuote\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newGovernancePending\",\"type\":\"address\"}],\"name\":\"initiateGovernanceTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeamMultisigPending\",\"type\":\"address\"}],\"name\":\"initiateTeamMultisigTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"insuranceFund\",\"outputs\":[{\"internalType\":\"contract IInsuranceFund\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"}],\"name\":\"liquidateLiquidityPositions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"targetAccountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"liquidateTokenPosition\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"keeperFee\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"enum IClearingHouseEnums.MulticallOperationType\",\"name\":\"operationType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct IClearingHouseStructures.MulticallOperation[]\",\"name\":\"operations\",\"type\":\"tuple[]\"}],\"name\":\"multicallWithSingleMarginCheck\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numAccounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfPoolsToUpdateInThisTx\",\"type\":\"uint256\"}],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rageTradeFactoryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IVToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"contract IUniswapV3Pool\",\"name\":\"vPool\",\"type\":\"address\"},{\"internalType\":\"contract IVPoolWrapper\",\"name\":\"vPoolWrapper\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"initialMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maintainanceMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maxVirtualPriceDeviationRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForTrade\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isCrossMargined\",\"type\":\"bool\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"internalType\":\"struct IClearingHouseStructures.PoolSettings\",\"name\":\"settings\",\"type\":\"tuple\"}],\"internalType\":\"struct IClearingHouseStructures.Pool\",\"name\":\"poolInfo\",\"type\":\"tuple\"}],\"name\":\"registerPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"}],\"name\":\"removeLimitOrder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"}],\"name\":\"settleProfit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"amount\",\"type\":\"int256\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceLimit\",\"type\":\"uint160\"},{\"internalType\":\"bool\",\"name\":\"isNotional\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isPartialAllowed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"settleProfit\",\"type\":\"bool\"}],\"internalType\":\"struct IClearingHouseStructures.SwapParams\",\"name\":\"swapParams\",\"type\":\"tuple\"}],\"name\":\"swapToken\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"vTokenAmountOut\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"vQuoteAmountOut\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamMultisig\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamMultisigPending\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfPoolsToUpdateInThisTx\",\"type\":\"uint256\"}],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"cToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct IClearingHouseStructures.CollateralSettings\",\"name\":\"collateralSettings\",\"type\":\"tuple\"}],\"name\":\"updateCollateralSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"collateralId\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"amount\",\"type\":\"int256\"}],\"name\":\"updateMargin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"initialMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maintainanceMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maxVirtualPriceDeviationRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForTrade\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isCrossMargined\",\"type\":\"bool\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"internalType\":\"struct IClearingHouseStructures.PoolSettings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updatePoolSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"amount\",\"type\":\"int256\"}],\"name\":\"updateProfit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"rangeLiquidationFeeFraction\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"tokenLiquidationFeeFraction\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"closeFactorMMThresholdBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"partialLiquidationCloseFactorBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"insuranceFundFeeShareBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"liquidationSlippageSqrtToleranceBps\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"maxRangeLiquidationFees\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minNotionalLiquidatable\",\"type\":\"uint64\"}],\"internalType\":\"struct IClearingHouseStructures.LiquidationParams\",\"name\":\"_liquidationParams\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_removeLimitOrderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOrderNotional\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minRequiredMargin\",\"type\":\"uint256\"}],\"name\":\"updateProtocolSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"int128\",\"name\":\"liquidityDelta\",\"type\":\"int128\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceCurrent\",\"type\":\"uint160\"},{\"internalType\":\"uint16\",\"name\":\"slippageToleranceBps\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"closeTokenPosition\",\"type\":\"bool\"},{\"internalType\":\"enum IClearingHouseEnums.LimitOrderType\",\"name\":\"limitOrderType\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"settleProfit\",\"type\":\"bool\"}],\"internalType\":\"struct IClearingHouseStructures.LiquidityChangeParams\",\"name\":\"liquidityChangeParams\",\"type\":\"tuple\"}],\"name\":\"updateRangeOrder\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"vTokenAmountOut\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"vQuoteAmountOut\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfPoolsToUpdateInThisTx\",\"type\":\"uint256\"}],\"name\":\"withdrawProtocolFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessDenied(address)\":[{\"params\":{\"senderAddress\":\"address of msg sender\"}}],\"CollateralDoesNotExist(uint32)\":[{\"params\":{\"collateralId\":\"address of token\"}}],\"CollateralNotAllowedForUse(uint32)\":[{\"params\":{\"collateralId\":\"address of token\"}}],\"IncorrectCollateralAddress(address,address)\":[{\"params\":{\"correctAddress\":\"correct address of collateral token\",\"incorrectAddress\":\"incorrect address of collateral token\"}}],\"InvalidCollateralAddress(address)\":[{\"params\":{\"invalidAddress\":\"invalid address of collateral token\"}}],\"InvalidMulticallOperationType(uint8)\":[{\"params\":{\"multicallOperationType\":\"is the value that is out of bounds\"}}],\"LowNotionalValue(uint256)\":[{\"params\":{\"notionalValue\":\"notional value of txn\"}}],\"PoolDoesNotExist(uint32)\":[{\"params\":{\"poolId\":\"unitialized truncated address supplied\"}}],\"PoolNotAllowedForTrade(uint32)\":[{\"params\":{\"poolId\":\"address of token\"}}]},\"kind\":\"dev\",\"methods\":{\"createAccount()\":{\"returns\":{\"newAccountId\":\"- serial number of the new account created\"}},\"createAccountAndAddMargin(uint32,uint256)\":{\"params\":{\"amount\":\"amount of token to deposit\",\"collateralId\":\"truncated address of collateral token to deposit\"},\"returns\":{\"newAccountId\":\"- serial number of the new account created\"}},\"extsload(bytes32)\":{\"params\":{\"slot\":\"to read from.\"},\"returns\":{\"val\":\"stored at the slot.\"}},\"extsload(bytes32[])\":{\"params\":{\"slots\":\"to read from.\"},\"returns\":{\"_0\":\"values stored at the slots.\"}},\"getAccountMarketValueAndRequiredMargin(uint256,bool)\":{\"details\":\"This method can be used to check if an account is under water or not. If accountMarketValue < requiredMargin then liquidation can take place.\",\"params\":{\"accountId\":\"the account id\",\"isInitialMargin\":\"true is initial margin, false is maintainance margin\"},\"returns\":{\"marketValue\":\"the market value of the account, due to collateral and positions\",\"requiredMargin\":\"margin needed due to positions\"}},\"getAccountNetProfit(uint256)\":{\"params\":{\"accountId\":\"the account id\"},\"returns\":{\"accountNetProfit\":\"the net profit of the account\"}},\"getAccountNetTokenPosition(uint256,uint32)\":{\"params\":{\"accountId\":\"the account id\",\"poolId\":\"the id of the pool (vETH, ... etc)\"},\"returns\":{\"netPosition\":\"the net position of the account\"}},\"getRealTwapPriceX128(uint32)\":{\"params\":{\"poolId\":\"the id of the pool\"},\"returns\":{\"realPriceX128\":\"the real price of the pool\"}},\"getVirtualTwapPriceX128(uint32)\":{\"params\":{\"poolId\":\"the id of the pool\"},\"returns\":{\"virtualPriceX128\":\"the virtual price of the pool\"}},\"initiateGovernanceTransfer(address)\":{\"params\":{\"newGovernancePending\":\"the new governance address\"}},\"initiateTeamMultisigTransfer(address)\":{\"params\":{\"newTeamMultisigPending\":\"the new team multisig address\"}},\"liquidateLiquidityPositions(uint256)\":{\"details\":\"removes all the active range positions and gives liquidator a percent of notional amount closed + fixedFee\",\"params\":{\"accountId\":\"account id\"}},\"liquidateTokenPosition(uint256,uint32)\":{\"details\":\"transfers the fraction of token position at a discount to current price to liquidators account and gives liquidator some fixedFee\",\"params\":{\"poolId\":\"truncated address of token to withdraw\",\"targetAccountId\":\"account id\"},\"returns\":{\"keeperFee\":\"- amount of fees transferred to keeper\"}},\"multicall(bytes[])\":{\"details\":\"The `msg.value` should not be trusted for any method callable from multicall.\",\"params\":{\"data\":\"The encoded function data for each of the calls to make to this contract\"},\"returns\":{\"results\":\"The results from each of the calls passed in via data\"}},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"removeLimitOrder(uint256,uint32,int24,int24)\":{\"details\":\"checks the position of current price relative to limit order and checks limitOrderType\",\"params\":{\"accountId\":\"account id\",\"poolId\":\"truncated address of token to withdraw\",\"tickLower\":\"liquidity change parameters\",\"tickUpper\":\"liquidity change parameters\"}},\"settleProfit(uint256)\":{\"params\":{\"accountId\":\"account id\"}},\"swapToken(uint256,uint32,(int256,uint160,bool,bool,bool))\":{\"params\":{\"accountId\":\"account id\",\"poolId\":\"truncated address of token to withdraw\",\"swapParams\":\"swap parameters\"}},\"updateMargin(uint256,uint32,int256)\":{\"params\":{\"accountId\":\"account id\",\"amount\":\"amount of token to deposit\",\"collateralId\":\"truncated address of token to deposit\"}},\"updatePoolSettings(uint32,(uint16,uint16,uint16,uint32,bool,bool,address))\":{\"params\":{\"newSettings\":\"updated rage trade pool settings\",\"poolId\":\"rage trade pool id\"}},\"updateProfit(uint256,int256)\":{\"params\":{\"accountId\":\"account id\",\"amount\":\"amount of token to withdraw\"}},\"updateRangeOrder(uint256,uint32,(int24,int24,int128,uint160,uint16,bool,uint8,bool))\":{\"params\":{\"accountId\":\"account id\",\"liquidityChangeParams\":\"liquidity change parameters\",\"poolId\":\"truncated address of token to withdraw\"}},\"withdrawProtocolFee(uint256)\":{\"params\":{\"numberOfPoolsToUpdateInThisTx\":\"number of pools to collect fees from\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"AccessDenied(address)\":[{\"notice\":\"error to denote invalid account access\"}],\"CannotPauseIfUnpauseInProgress()\":[{\"notice\":\"error to denote unpause is in progress, hence cannot pause\"}],\"CannotUnpauseIfPauseInProgress()\":[{\"notice\":\"error to denote pause is in progress, hence cannot unpause\"}],\"CollateralDoesNotExist(uint32)\":[{\"notice\":\"error to denote usage of uninitialized token\"}],\"CollateralNotAllowedForUse(uint32)\":[{\"notice\":\"error to denote usage of unsupported collateral token\"}],\"IncorrectCollateralAddress(address,address)\":[{\"notice\":\"error to denote incorrect address is supplied while updating collateral settings\"}],\"InvalidCollateralAddress(address)\":[{\"notice\":\"error to denote invalid address supplied as a collateral token\"}],\"InvalidMulticallOperationType(uint8)\":[{\"notice\":\"this is errored when the enum (uint8) value is out of bounds\"}],\"InvalidSetting(uint256)\":[{\"notice\":\"error to denote an invalid setting for parameters\"}],\"InvalidTokenLiquidationParameters()\":[{\"notice\":\"error to denote invalid token liquidation (fraction to liquidate> 1)\"}],\"KeeperFeeNotPositive(int256)\":[{\"notice\":\"error to denote that keeper fee is negative or zero\"}],\"LowNotionalValue(uint256)\":[{\"notice\":\"error to denote low notional value of txn\"}],\"NotRageTradeFactory()\":[{\"notice\":\"error to denote that caller is not ragetrade factory\"}],\"PoolDoesNotExist(uint32)\":[{\"notice\":\"error to denote usage of uninitialized pool\"}],\"PoolNotAllowedForTrade(uint32)\":[{\"notice\":\"error to denote usage of unsupported pool\"}],\"SlippageBeyondTolerance()\":[{\"notice\":\"error to denote slippage of txn beyond set threshold\"}],\"ZeroAmount()\":[{\"notice\":\"error to denote that zero amount is passed and it's prohibited\"}]},\"events\":{\"AccountCreated(address,uint256)\":{\"notice\":\"denotes new account creation\"},\"CollateralSettingsUpdated(address,(address,uint32,bool))\":{\"notice\":\"new collateral supported as margin\"},\"PoolSettingsUpdated(uint32,(uint16,uint16,uint16,uint32,bool,bool,address))\":{\"notice\":\"maintainance margin ratio of a pool changed\"},\"ProtocolSettingsUpdated((uint16,uint16,uint16,uint16,uint16,uint16,uint64,uint64),uint256,uint256,uint256)\":{\"notice\":\"protocol settings changed\"}},\"kind\":\"user\",\"methods\":{\"acceptGovernanceTransfer()\":{\"notice\":\"Completes governance transfer, on being called by _governancePending.\"},\"acceptTeamMultisigTransfer()\":{\"notice\":\"Completes teamMultisig transfer, on being called by _teamMultisigPending.\"},\"createAccount()\":{\"notice\":\"creates a new account and adds it to the accounts map\"},\"createAccountAndAddMargin(uint32,uint256)\":{\"notice\":\"creates a new account and deposits 'amount' of token associated with 'poolId'\"},\"extsload(bytes32)\":{\"notice\":\"Returns a value from the storage.\"},\"extsload(bytes32[])\":{\"notice\":\"Returns multiple values from storage.\"},\"getAccountMarketValueAndRequiredMargin(uint256,bool)\":{\"notice\":\"Gets the market value and required margin of an account\"},\"getAccountNetProfit(uint256)\":{\"notice\":\"Gets the net profit of an account\"},\"getAccountNetTokenPosition(uint256,uint32)\":{\"notice\":\"Gets the net position of an account\"},\"getRealTwapPriceX128(uint32)\":{\"notice\":\"Gets the real twap price from the respective oracle of the given poolId\"},\"getVirtualTwapPriceX128(uint32)\":{\"notice\":\"Gets the virtual twap price from the respective oracle of the given poolId\"},\"governance()\":{\"notice\":\"Returns the address of the current governance.\"},\"governancePending()\":{\"notice\":\"Returns the address of the current governance.\"},\"initialize(address,address,address,address,address,address,address)\":{\"notice\":\"SYSTEM FUNCTIONS\"},\"initiateGovernanceTransfer(address)\":{\"notice\":\"Initiates governance transfer to a new account (`newGovernancePending`).\"},\"initiateTeamMultisigTransfer(address)\":{\"notice\":\"Initiates teamMultisig transfer to a new account (`newTeamMultisigPending`).\"},\"liquidateLiquidityPositions(uint256)\":{\"notice\":\"keeper call for liquidation of range position\"},\"liquidateTokenPosition(uint256,uint32)\":{\"notice\":\"keeper call for liquidation of token position\"},\"multicall(bytes[])\":{\"notice\":\"Call multiple functions in the current contract and return the data from all of them if they all succeed\"},\"multicallWithSingleMarginCheck(uint256,(uint8,bytes)[])\":{\"notice\":\"MULTICALL\"},\"removeLimitOrder(uint256,uint32,int24,int24)\":{\"notice\":\"keeper call to remove a limit order\"},\"settleProfit(uint256)\":{\"notice\":\"settles the profit/loss made with the settlement token collateral deposits\"},\"swapToken(uint256,uint32,(int256,uint160,bool,bool,bool))\":{\"notice\":\"swaps token associated with 'poolId' by 'amount' (Long if amount>0 else Short)\"},\"teamMultisig()\":{\"notice\":\"Returns the address of the current team multisig.transferTeamMultisig\"},\"teamMultisigPending()\":{\"notice\":\"Returns the address of the current team multisig.transferTeamMultisig\"},\"updateCollateralSettings(address,(address,uint32,bool))\":{\"notice\":\"ADMIN FUNCTIONS\"},\"updateMargin(uint256,uint32,int256)\":{\"notice\":\"deposits 'amount' of token associated with 'poolId'\"},\"updatePoolSettings(uint32,(uint16,uint16,uint16,uint32,bool,bool,address))\":{\"notice\":\"updates the rage trade pool settings\"},\"updateProfit(uint256,int256)\":{\"notice\":\"withdraws 'amount' of settlement token from the profit made\"},\"updateRangeOrder(uint256,uint32,(int24,int24,int128,uint160,uint16,bool,uint8,bool))\":{\"notice\":\"updates range order of token associated with 'poolId' by 'liquidityDelta' (Adds if amount>0 else Removes)also can be used to update limitOrderType\"},\"withdrawProtocolFee(uint256)\":{\"notice\":\"withdraws protocol fees collected in the supplied wrappers to team multisig\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/protocol/clearinghouse/ClearingHouse.sol\":\"ClearingHouse\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":4999},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the\\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() initializer {}\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\\n // contract may have been reentered.\\n require(_initializing ? _isConstructor() : !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} modifier, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n function _isConstructor() private view returns (bool) {\\n return !AddressUpgradeable.isContract(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x372b0bc04e3b4c074559bbbfb1317afddb56de5504158ca25a7f9cd403980445\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x041af89e5e60b74e1203d5a34614c9de379726f52ecb8cf064cab78b9fdcdf9d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\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\":\"0x55cf2bd9fc76704ddcdc19834cd288b7de00fc0f298a40ea16a954ae8991db2d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\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\":\"0xbbc8ac883ac3c0078ce5ad3e288fbb3ffcc8a30c3a98c0fda0114d64fc44fca2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\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\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a / b + (a % b == 0 ? 0 : 1);\\n }\\n}\\n\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport {IUniswapV3PoolImmutables} from './pool/IUniswapV3PoolImmutables.sol';\\nimport {IUniswapV3PoolState} from './pool/IUniswapV3PoolState.sol';\\nimport {IUniswapV3PoolDerivedState} from './pool/IUniswapV3PoolDerivedState.sol';\\nimport {IUniswapV3PoolActions} from './pool/IUniswapV3PoolActions.sol';\\nimport {IUniswapV3PoolOwnerActions} from './pool/IUniswapV3PoolOwnerActions.sol';\\nimport {IUniswapV3PoolErrors} from './pool/IUniswapV3PoolErrors.sol';\\nimport {IUniswapV3PoolEvents} from './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 IUniswapV3PoolErrors,\\n IUniswapV3PoolEvents\\n{\\n\\n}\\n\",\"keccak256\":\"0x4e64844c56061cd90e0a80de73534a9166704c43eed579eb83f90bc2780ce968\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/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-0.8-support/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-0.8-support/contracts/interfaces/pool/IUniswapV3PoolErrors.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Errors emitted by a pool\\n/// @notice Contains all events emitted by the pool\\ninterface IUniswapV3PoolErrors {\\n error LOK();\\n error TLU();\\n error TLM();\\n error TUM();\\n error AI();\\n error M0();\\n error M1();\\n error AS();\\n error IIA();\\n error L();\\n error F0();\\n error F1();\\n}\\n\",\"keccak256\":\"0xf80abf13fb1fafc127ba4e792f240dd8ea7c8c893978cdfd8439c27fae9a037b\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/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-0.8-support/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-0.8-support/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-0.8-support/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 /// @return 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 /// @return observationIndex The index of the last oracle observation that was written,\\n /// @return observationCardinality The current maximum number of observations stored in the pool,\\n /// @return observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n /// @return 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 /// @return The liquidity at the current price of the pool\\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 /// @return liquidityNet how much liquidity changes when the pool price crosses the tick,\\n /// @return feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n /// @return feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n /// @return tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n /// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n /// @return secondsOutside the seconds spent on the other side of the tick from the current tick,\\n /// @return 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 /// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n /// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n /// @return tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n /// @return 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 /// @return tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n /// @return secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n /// @return 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\":\"0x44fa2ce1182f6c2f6bead3d1737804bf7e112252ae86e0f2e92f9b8249603f43\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.4.0;\\n\\n/// @title FixedPoint128\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\nlibrary FixedPoint128 {\\n uint256 internal constant Q128 = 0x100000000000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x2d1f4f73ae0d8f0a210b8d30084659b57c56ac8f2f96011fca36f00a6d417178\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/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-0.8-support/contracts/libraries/FullMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.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 unchecked {\\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 = (0 - 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\\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 unchecked {\\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}\\n\",\"keccak256\":\"0x7825565a4bb2a34a1dc96bbfead755785dfb0df8ef81bd934c43023689685645\",\"license\":\"MIT\"},\"@uniswap/v3-core-0.8-support/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-0.8-support/contracts/libraries/SqrtPriceMath.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\nimport {SafeCast} from './SafeCast.sol';\\n\\nimport {FullMath} from './FullMath.sol';\\nimport {UnsafeMath} from './UnsafeMath.sol';\\nimport {FixedPoint96} from './FixedPoint96.sol';\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Contains the math that uses square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMath {\\n using SafeCast for uint256;\\n\\n /// @notice Gets the next sqrt price given a delta of token0\\n /// @dev Always rounds up, because in the exact output case (increasing price) we need to move the price at least\\n /// far enough to get the desired output amount, and in the exact input case (decreasing price) we need to move the\\n /// price less in order to not send too much output.\\n /// The most precise formula for this is liquidity * sqrtPX96 / (liquidity +- amount * sqrtPX96),\\n /// if this is impossible because of overflow, we calculate liquidity / (liquidity / sqrtPX96 +- amount).\\n /// @param sqrtPX96 The starting price, i.e. before accounting for the token0 delta\\n /// @param liquidity The amount of usable liquidity\\n /// @param amount How much of token0 to add or remove from virtual reserves\\n /// @param add Whether to add or remove the amount of token0\\n /// @return The price after adding or removing amount, depending on add\\n function getNextSqrtPriceFromAmount0RoundingUp(\\n uint160 sqrtPX96,\\n uint128 liquidity,\\n uint256 amount,\\n bool add\\n ) internal pure returns (uint160) {\\n // we short circuit amount == 0 because the result is otherwise not guaranteed to equal the input price\\n if (amount == 0) return sqrtPX96;\\n uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n\\n if (add) {\\n unchecked {\\n uint256 product;\\n if ((product = amount * sqrtPX96) / amount == sqrtPX96) {\\n uint256 denominator = numerator1 + product;\\n if (denominator >= numerator1)\\n // always fits in 160 bits\\n return uint160(FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator));\\n }\\n }\\n // denominator is checked for overflow\\n return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96) + amount));\\n } else {\\n unchecked {\\n uint256 product;\\n // if the product overflows, we know the denominator underflows\\n // in addition, we must check that the denominator does not underflow\\n require((product = amount * sqrtPX96) / amount == sqrtPX96 && numerator1 > product);\\n uint256 denominator = numerator1 - product;\\n return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator).toUint160();\\n }\\n }\\n }\\n\\n /// @notice Gets the next sqrt price given a delta of token1\\n /// @dev Always rounds down, because in the exact output case (decreasing price) we need to move the price at least\\n /// far enough to get the desired output amount, and in the exact input case (increasing price) we need to move the\\n /// price less in order to not send too much output.\\n /// The formula we compute is within <1 wei of the lossless version: sqrtPX96 +- amount / liquidity\\n /// @param sqrtPX96 The starting price, i.e., before accounting for the token1 delta\\n /// @param liquidity The amount of usable liquidity\\n /// @param amount How much of token1 to add, or remove, from virtual reserves\\n /// @param add Whether to add, or remove, the amount of token1\\n /// @return The price after adding or removing `amount`\\n function getNextSqrtPriceFromAmount1RoundingDown(\\n uint160 sqrtPX96,\\n uint128 liquidity,\\n uint256 amount,\\n bool add\\n ) internal pure returns (uint160) {\\n // if we're adding (subtracting), rounding down requires rounding the quotient down (up)\\n // in both cases, avoid a mulDiv for most inputs\\n if (add) {\\n uint256 quotient = (\\n amount <= type(uint160).max\\n ? (amount << FixedPoint96.RESOLUTION) / liquidity\\n : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\n );\\n\\n return (uint256(sqrtPX96) + quotient).toUint160();\\n } else {\\n uint256 quotient = (\\n amount <= type(uint160).max\\n ? UnsafeMath.divRoundingUp(amount << FixedPoint96.RESOLUTION, liquidity)\\n : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity)\\n );\\n\\n require(sqrtPX96 > quotient);\\n // always fits 160 bits\\n unchecked {\\n return uint160(sqrtPX96 - quotient);\\n }\\n }\\n }\\n\\n /// @notice Gets the next sqrt price given an input amount of token0 or token1\\n /// @dev Throws if price or liquidity are 0, or if the next price is out of bounds\\n /// @param sqrtPX96 The starting price, i.e., before accounting for the input amount\\n /// @param liquidity The amount of usable liquidity\\n /// @param amountIn How much of token0, or token1, is being swapped in\\n /// @param zeroForOne Whether the amount in is token0 or token1\\n /// @return sqrtQX96 The price after adding the input amount to token0 or token1\\n function getNextSqrtPriceFromInput(\\n uint160 sqrtPX96,\\n uint128 liquidity,\\n uint256 amountIn,\\n bool zeroForOne\\n ) internal pure returns (uint160 sqrtQX96) {\\n require(sqrtPX96 > 0);\\n require(liquidity > 0);\\n\\n // round to make sure that we don't pass the target price\\n return\\n zeroForOne\\n ? getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true)\\n : getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true);\\n }\\n\\n /// @notice Gets the next sqrt price given an output amount of token0 or token1\\n /// @dev Throws if price or liquidity are 0 or the next price is out of bounds\\n /// @param sqrtPX96 The starting price before accounting for the output amount\\n /// @param liquidity The amount of usable liquidity\\n /// @param amountOut How much of token0, or token1, is being swapped out\\n /// @param zeroForOne Whether the amount out is token0 or token1\\n /// @return sqrtQX96 The price after removing the output amount of token0 or token1\\n function getNextSqrtPriceFromOutput(\\n uint160 sqrtPX96,\\n uint128 liquidity,\\n uint256 amountOut,\\n bool zeroForOne\\n ) internal pure returns (uint160 sqrtQX96) {\\n require(sqrtPX96 > 0);\\n require(liquidity > 0);\\n\\n // round to make sure that we pass the target price\\n return\\n zeroForOne\\n ? getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false)\\n : getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false);\\n }\\n\\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 ) internal pure returns (uint256 amount0) {\\n unchecked {\\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\\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 ) internal pure returns (uint256 amount1) {\\n unchecked {\\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\\n /// @notice Helper that gets signed token0 delta\\n /// @param sqrtRatioAX96 A sqrt price\\n /// @param sqrtRatioBX96 Another sqrt price\\n /// @param liquidity The change in liquidity for which to compute the amount0 delta\\n /// @return amount0 Amount of token0 corresponding to the passed liquidityDelta between the two prices\\n function getAmount0Delta(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n int128 liquidity\\n ) internal pure returns (int256 amount0) {\\n unchecked {\\n return\\n liquidity < 0\\n ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n }\\n }\\n\\n /// @notice Helper that gets signed token1 delta\\n /// @param sqrtRatioAX96 A sqrt price\\n /// @param sqrtRatioBX96 Another sqrt price\\n /// @param liquidity The change in liquidity for which to compute the amount1 delta\\n /// @return amount1 Amount of token1 corresponding to the passed liquidityDelta between the two prices\\n function getAmount1Delta(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n int128 liquidity\\n ) internal pure returns (int256 amount1) {\\n unchecked {\\n return\\n liquidity < 0\\n ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe73eb517e348c084771c6204eb698fce95657901454ad0f394acf5192b709b97\",\"license\":\"BUSL-1.1\"},\"@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity ^0.8.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 error T();\\n error R();\\n\\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 unchecked {\\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n if (absTick > uint256(int256(MAX_TICK))) revert T();\\n\\n uint256 ratio = absTick & 0x1 != 0\\n ? 0xfffcb933bd6fad37aa2d162d1a594001\\n : 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\\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 unchecked {\\n // second inequality must be < because the price can never reach the price at the max tick\\n if (!(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO)) revert 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}\\n\",\"keccak256\":\"0x5c57de03a91cc2ec8939865dbbcb0197bb6c353b711075eefd8e0fca5e102129\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/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/IMulticall.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Multicall interface\\n/// @notice Enables calling multiple methods in a single call to the contract\\ninterface IMulticall {\\n /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed\\n /// @dev The `msg.value` should not be trusted for any method callable from multicall.\\n /// @param data The encoded function data for each of the calls to make to this contract\\n /// @return results The results from each of the calls passed in via data\\n function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0xa8f9d0061ee730a522dc4bae6bd5cabb3e997e2c5983da183e912bdca93dfa7b\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IClearingHouse.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IGovernable } from './IGovernable.sol';\\n\\nimport { IClearingHouseActions } from './clearinghouse/IClearingHouseActions.sol';\\nimport { IClearingHouseCustomErrors } from './clearinghouse/IClearingHouseCustomErrors.sol';\\nimport { IClearingHouseEnums } from './clearinghouse/IClearingHouseEnums.sol';\\nimport { IClearingHouseEvents } from './clearinghouse/IClearingHouseEvents.sol';\\nimport { IClearingHouseOwnerActions } from './clearinghouse/IClearingHouseOwnerActions.sol';\\nimport { IClearingHouseStructures } from './clearinghouse/IClearingHouseStructures.sol';\\nimport { IClearingHouseSystemActions } from './clearinghouse/IClearingHouseSystemActions.sol';\\nimport { IClearingHouseView } from './clearinghouse/IClearingHouseView.sol';\\n\\ninterface IClearingHouse is\\n IGovernable,\\n IClearingHouseEnums,\\n IClearingHouseStructures,\\n IClearingHouseActions,\\n IClearingHouseCustomErrors,\\n IClearingHouseEvents,\\n IClearingHouseOwnerActions,\\n IClearingHouseSystemActions,\\n IClearingHouseView\\n{}\\n\",\"keccak256\":\"0xefcfad57b4aee9e20f34bb2809f69fcea692f67344e301b321ae60fa79f27c21\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IExtsload.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\n/// @title This is an interface to read contract's state that supports extsload.\\ninterface IExtsload {\\n /// @notice Returns a value from the storage.\\n /// @param slot to read from.\\n /// @return value stored at the slot.\\n function extsload(bytes32 slot) external view returns (bytes32 value);\\n\\n /// @notice Returns multiple values from storage.\\n /// @param slots to read from.\\n /// @return values stored at the slots.\\n function extsload(bytes32[] memory slots) external view returns (bytes32[] memory);\\n}\\n\",\"keccak256\":\"0x9b2387dbfb081f98a6d21ed1b7297668cda241fc1cea540fc0127f140a982d17\",\"license\":\"MIT\"},\"contracts/interfaces/IGovernable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\ninterface IGovernable {\\n function governance() external view returns (address);\\n\\n function governancePending() external view returns (address);\\n\\n function teamMultisig() external view returns (address);\\n\\n function teamMultisigPending() external view returns (address);\\n\\n function initiateGovernanceTransfer(address newGovernancePending) external;\\n\\n function acceptGovernanceTransfer() external;\\n\\n function initiateTeamMultisigTransfer(address newTeamMultisigPending) external;\\n\\n function acceptTeamMultisigTransfer() external;\\n}\\n\",\"keccak256\":\"0x28ac4a7bea6877cc7f831047aea9a26d7d30f787f15b1773e020287d06f02b75\",\"license\":\"MIT\"},\"contracts/interfaces/IInsuranceFund.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\ninterface IInsuranceFund {\\n function initialize(\\n IERC20 settlementToken,\\n address clearingHouse,\\n string calldata name,\\n string calldata symbol\\n ) external;\\n\\n function claim(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x8ce253b8c14252cdb8a8607f0014dbd70d168b999c061da4db4959c91660bc87\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\ninterface IOracle {\\n function getTwapPriceX128(uint32 twapDuration) external view returns (uint256 priceX128);\\n}\\n\",\"keccak256\":\"0x0b868e6dbb5dbbe067f65dda1a2c405a124142dbd936deeb4cc995ceb9ab232e\",\"license\":\"MIT\"},\"contracts/interfaces/IVPoolWrapper.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { IVQuote } from './IVQuote.sol';\\nimport { IVToken } from './IVToken.sol';\\n\\ninterface IVPoolWrapper {\\n struct InitializeVPoolWrapperParams {\\n address clearingHouse; // address of clearing house contract (proxy)\\n IVToken vToken; // address of vToken contract\\n IVQuote vQuote; // address of vQuote contract\\n IUniswapV3Pool vPool; // address of Uniswap V3 Pool contract, created using vToken and vQuote\\n uint24 liquidityFeePips; // liquidity fee fraction (in 1e6)\\n uint24 protocolFeePips; // protocol fee fraction (in 1e6)\\n }\\n\\n struct SwapResult {\\n int256 amountSpecified; // amount of tokens/vQuote which were specified in the swap request\\n int256 vTokenIn; // actual amount of vTokens paid by account to the Pool\\n int256 vQuoteIn; // actual amount of vQuotes paid by account to the Pool\\n uint256 liquidityFees; // actual amount of fees paid by account to the Pool\\n uint256 protocolFees; // actual amount of fees paid by account to the Protocol\\n uint160 sqrtPriceX96Start; // sqrt price at the beginning of the swap\\n uint160 sqrtPriceX96End; // sqrt price at the end of the swap\\n }\\n\\n struct WrapperValuesInside {\\n int256 sumAX128; // sum of all the A terms in the pool\\n int256 sumBInsideX128; // sum of all the B terms in side the tick range in the pool\\n int256 sumFpInsideX128; // sum of all the Fp terms in side the tick range in the pool\\n uint256 sumFeeInsideX128; // sum of all the fee terms in side the tick range in the pool\\n }\\n\\n /// @notice Emitted whenever a swap takes place\\n /// @param swapResult the swap result values\\n event Swap(SwapResult swapResult);\\n\\n /// @notice Emitted whenever liquidity is added\\n /// @param tickLower the lower tick of the range\\n /// @param tickUpper the upper tick of the range\\n /// @param liquidity the amount of liquidity that was added\\n /// @param vTokenPrincipal the amount of vToken that was sent to UniswapV3Pool\\n /// @param vQuotePrincipal the mount of vQuote charged was sent to UniswapV3Pool\\n event Mint(int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 vTokenPrincipal, uint256 vQuotePrincipal);\\n\\n /// @notice Emitted whenever liquidity is removed\\n /// @param tickLower the lower tick of the range\\n /// @param tickUpper the upper tick of the range\\n /// @param liquidity the amount of liquidity that was removed\\n /// @param vTokenPrincipal the amount of vToken that was received from UniswapV3Pool\\n /// @param vQuotePrincipal the mount of vQuote charged was received from UniswapV3Pool\\n event Burn(int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 vTokenPrincipal, uint256 vQuotePrincipal);\\n\\n /// @notice Emitted whenever clearing house enquired about the accrued protocol fees\\n /// @param amount the amount of accrued protocol fees\\n event AccruedProtocolFeeCollected(uint256 amount);\\n\\n /// @notice Emitted when governance updates the liquidity fees\\n /// @param liquidityFeePips the new liquidity fee ratio\\n event LiquidityFeeUpdated(uint24 liquidityFeePips);\\n\\n /// @notice Emitted when governance updates the protocol fees\\n /// @param protocolFeePips the new protocol fee ratio\\n event ProtocolFeeUpdated(uint24 protocolFeePips);\\n\\n /// @notice Emitted when funding rate override is updated\\n /// @param fundingRateOverrideX128 the new funding rate override value\\n event FundingRateOverrideUpdated(int256 fundingRateOverrideX128);\\n\\n function initialize(InitializeVPoolWrapperParams memory params) external;\\n\\n function vPool() external view returns (IUniswapV3Pool);\\n\\n function getValuesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (WrapperValuesInside memory wrapperValuesInside);\\n\\n function getExtrapolatedValuesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (WrapperValuesInside memory wrapperValuesInside);\\n\\n function swap(\\n bool swapVTokenForVQuote, // zeroForOne\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96\\n ) external returns (SwapResult memory swapResult);\\n\\n function mint(\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity\\n )\\n external\\n returns (\\n uint256 vTokenPrincipal,\\n uint256 vQuotePrincipal,\\n WrapperValuesInside memory wrapperValuesInside\\n );\\n\\n function burn(\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity\\n )\\n external\\n returns (\\n uint256 vTokenPrincipal,\\n uint256 vQuotePrincipal,\\n WrapperValuesInside memory wrapperValuesInside\\n );\\n\\n function getSumAX128() external view returns (int256);\\n\\n function getExtrapolatedSumAX128() external view returns (int256);\\n\\n function liquidityFeePips() external view returns (uint24);\\n\\n function protocolFeePips() external view returns (uint24);\\n\\n /// @notice Used by clearing house to update funding rate when clearing house is paused or unpaused.\\n /// @param useZeroFundingRate: used to discount funding payment during the duration ch was paused.\\n function updateGlobalFundingState(bool useZeroFundingRate) external;\\n\\n /// @notice Used by clearing house to know how much protocol fee was collected.\\n /// @return accruedProtocolFeeLast amount of protocol fees accrued since last collection.\\n /// @dev Does not do any token transfer, just reduces the state in wrapper by accruedProtocolFeeLast.\\n /// Clearing house already has the amount of settlement tokens to send to treasury.\\n function collectAccruedProtocolFee() external returns (uint256 accruedProtocolFeeLast);\\n}\\n\",\"keccak256\":\"0x5f8ffc93fbd71f02a3da23e4b7f2c8d2b4d1f879fe31e6acdcfa787dffc3f72b\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IVQuote.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\ninterface IVQuote is IERC20 {\\n function mint(address account, uint256 amount) external;\\n\\n function burn(uint256 amount) external;\\n\\n function authorize(address vPoolWrapper) external;\\n}\\n\",\"keccak256\":\"0x77c3c0e1a7a1b9a10633953ac4824f14007af94c323e545b5ff12ef271416774\",\"license\":\"MIT\"},\"contracts/interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\ninterface IVToken is IERC20 {\\n function mint(address account, uint256 amount) external;\\n\\n function burn(uint256 amount) external;\\n\\n function setVPoolWrapper(address) external;\\n}\\n\",\"keccak256\":\"0x0ac091c87193f7a5703954bf6484f3a30310b414cdda75cd81a80df23035dfe2\",\"license\":\"MIT\"},\"contracts/interfaces/clearinghouse/IClearingHouseActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseActions is IClearingHouseStructures {\\n /// @notice creates a new account and adds it to the accounts map\\n /// @return newAccountId - serial number of the new account created\\n function createAccount() external returns (uint256 newAccountId);\\n\\n /// @notice deposits 'amount' of token associated with 'poolId'\\n /// @param accountId account id\\n /// @param collateralId truncated address of token to deposit\\n /// @param amount amount of token to deposit\\n function updateMargin(\\n uint256 accountId,\\n uint32 collateralId,\\n int256 amount\\n ) external;\\n\\n /// @notice creates a new account and deposits 'amount' of token associated with 'poolId'\\n /// @param collateralId truncated address of collateral token to deposit\\n /// @param amount amount of token to deposit\\n /// @return newAccountId - serial number of the new account created\\n function createAccountAndAddMargin(uint32 collateralId, uint256 amount) external returns (uint256 newAccountId);\\n\\n /// @notice withdraws 'amount' of settlement token from the profit made\\n /// @param accountId account id\\n /// @param amount amount of token to withdraw\\n function updateProfit(uint256 accountId, int256 amount) external;\\n\\n /// @notice settles the profit/loss made with the settlement token collateral deposits\\n /// @param accountId account id\\n function settleProfit(uint256 accountId) external;\\n\\n /// @notice swaps token associated with 'poolId' by 'amount' (Long if amount>0 else Short)\\n /// @param accountId account id\\n /// @param poolId truncated address of token to withdraw\\n /// @param swapParams swap parameters\\n function swapToken(\\n uint256 accountId,\\n uint32 poolId,\\n SwapParams memory swapParams\\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut);\\n\\n /// @notice updates range order of token associated with 'poolId' by 'liquidityDelta' (Adds if amount>0 else Removes)\\n /// @notice also can be used to update limitOrderType\\n /// @param accountId account id\\n /// @param poolId truncated address of token to withdraw\\n /// @param liquidityChangeParams liquidity change parameters\\n function updateRangeOrder(\\n uint256 accountId,\\n uint32 poolId,\\n LiquidityChangeParams calldata liquidityChangeParams\\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut);\\n\\n /// @notice keeper call to remove a limit order\\n /// @dev checks the position of current price relative to limit order and checks limitOrderType\\n /// @param accountId account id\\n /// @param poolId truncated address of token to withdraw\\n /// @param tickLower liquidity change parameters\\n /// @param tickUpper liquidity change parameters\\n function removeLimitOrder(\\n uint256 accountId,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper\\n ) external;\\n\\n /// @notice keeper call for liquidation of range position\\n /// @dev removes all the active range positions and gives liquidator a percent of notional amount closed + fixedFee\\n /// @param accountId account id\\n function liquidateLiquidityPositions(uint256 accountId) external;\\n\\n /// @notice keeper call for liquidation of token position\\n /// @dev transfers the fraction of token position at a discount to current price to liquidators account and gives liquidator some fixedFee\\n /// @param targetAccountId account id\\n /// @param poolId truncated address of token to withdraw\\n /// @return keeperFee - amount of fees transferred to keeper\\n function liquidateTokenPosition(uint256 targetAccountId, uint32 poolId) external returns (int256 keeperFee);\\n}\\n\",\"keccak256\":\"0x21b3310eeee56ef487f2a636019278dc6a59f9d1e40364989caf9013cee0de55\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseCustomErrors.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IVToken } from '../IVToken.sol';\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseCustomErrors is IClearingHouseStructures {\\n /// @notice error to denote invalid account access\\n /// @param senderAddress address of msg sender\\n error AccessDenied(address senderAddress);\\n\\n /// @notice error to denote usage of uninitialized token\\n /// @param collateralId address of token\\n error CollateralDoesNotExist(uint32 collateralId);\\n\\n /// @notice error to denote usage of unsupported collateral token\\n /// @param collateralId address of token\\n error CollateralNotAllowedForUse(uint32 collateralId);\\n\\n /// @notice error to denote unpause is in progress, hence cannot pause\\n error CannotPauseIfUnpauseInProgress();\\n\\n /// @notice error to denote pause is in progress, hence cannot unpause\\n error CannotUnpauseIfPauseInProgress();\\n\\n /// @notice error to denote incorrect address is supplied while updating collateral settings\\n /// @param incorrectAddress incorrect address of collateral token\\n /// @param correctAddress correct address of collateral token\\n error IncorrectCollateralAddress(IERC20 incorrectAddress, IERC20 correctAddress);\\n\\n /// @notice error to denote invalid address supplied as a collateral token\\n /// @param invalidAddress invalid address of collateral token\\n error InvalidCollateralAddress(address invalidAddress);\\n\\n /// @notice error to denote invalid token liquidation (fraction to liquidate> 1)\\n error InvalidTokenLiquidationParameters();\\n\\n /// @notice this is errored when the enum (uint8) value is out of bounds\\n /// @param multicallOperationType is the value that is out of bounds\\n error InvalidMulticallOperationType(MulticallOperationType multicallOperationType);\\n\\n /// @notice error to denote that keeper fee is negative or zero\\n error KeeperFeeNotPositive(int256 keeperFee);\\n\\n /// @notice error to denote low notional value of txn\\n /// @param notionalValue notional value of txn\\n error LowNotionalValue(uint256 notionalValue);\\n\\n /// @notice error to denote that caller is not ragetrade factory\\n error NotRageTradeFactory();\\n\\n /// @notice error to denote usage of uninitialized pool\\n /// @param poolId unitialized truncated address supplied\\n error PoolDoesNotExist(uint32 poolId);\\n\\n /// @notice error to denote usage of unsupported pool\\n /// @param poolId address of token\\n error PoolNotAllowedForTrade(uint32 poolId);\\n\\n /// @notice error to denote slippage of txn beyond set threshold\\n error SlippageBeyondTolerance();\\n\\n /// @notice error to denote that zero amount is passed and it's prohibited\\n error ZeroAmount();\\n\\n /// @notice error to denote an invalid setting for parameters\\n error InvalidSetting(uint256 errorCode);\\n}\\n\",\"keccak256\":\"0x0d0bafa321810a35b83b36d81507937ed5d132c65ee6ef05c92085bd31dd6ca8\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseEnums.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface IClearingHouseEnums {\\n enum LimitOrderType {\\n NONE,\\n LOWER_LIMIT,\\n UPPER_LIMIT\\n }\\n\\n enum MulticallOperationType {\\n UPDATE_MARGIN,\\n UPDATE_PROFIT,\\n SWAP_TOKEN,\\n UPDATE_RANGE_ORDER,\\n REMOVE_LIMIT_ORDER,\\n LIQUIDATE_LIQUIDITY_POSITIONS,\\n LIQUIDATE_TOKEN_POSITION\\n }\\n}\\n\",\"keccak256\":\"0xf9ad0cde3e59a661f70a3af28cc6f8cdba0bcfdbc2f8df3799a1e17c333db4b2\",\"license\":\"MIT\"},\"contracts/interfaces/clearinghouse/IClearingHouseEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IVToken } from '../IVToken.sol';\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseEvents is IClearingHouseStructures {\\n /// @notice denotes new account creation\\n /// @param ownerAddress wallet address of account owner\\n /// @param accountId serial number of the account\\n event AccountCreated(address indexed ownerAddress, uint256 accountId);\\n\\n /// @notice new collateral supported as margin\\n /// @param cTokenInfo collateral token info\\n event CollateralSettingsUpdated(IERC20 cToken, CollateralSettings cTokenInfo);\\n\\n /// @notice maintainance margin ratio of a pool changed\\n /// @param poolId id of the rage trade pool\\n /// @param settings new settings\\n event PoolSettingsUpdated(uint32 poolId, PoolSettings settings);\\n\\n /// @notice protocol settings changed\\n /// @param liquidationParams liquidation params\\n /// @param removeLimitOrderFee fee for remove limit order\\n /// @param minimumOrderNotional minimum order notional\\n /// @param minRequiredMargin minimum required margin\\n event ProtocolSettingsUpdated(\\n LiquidationParams liquidationParams,\\n uint256 removeLimitOrderFee,\\n uint256 minimumOrderNotional,\\n uint256 minRequiredMargin\\n );\\n\\n event PausedUpdated(bool paused);\\n}\\n\",\"keccak256\":\"0x40638408c2cf0484b8d11d937181711eb3ea61368133ed92134cd3a84cdf97e6\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseOwnerActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IVToken } from '../IVToken.sol';\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseOwnerActions is IClearingHouseStructures {\\n /// @notice updates the collataral settings\\n /// @param cToken collateral token\\n /// @param collateralSettings settings\\n function updateCollateralSettings(IERC20 cToken, CollateralSettings memory collateralSettings) external;\\n\\n /// @notice updates the rage trade pool settings\\n /// @param poolId rage trade pool id\\n /// @param newSettings updated rage trade pool settings\\n function updatePoolSettings(uint32 poolId, PoolSettings calldata newSettings) external;\\n\\n /// @notice updates the protocol settings\\n /// @param liquidationParams liquidation params\\n /// @param removeLimitOrderFee fee for remove limit order\\n /// @param minimumOrderNotional minimum order notional\\n /// @param minRequiredMargin minimum required margin\\n function updateProtocolSettings(\\n LiquidationParams calldata liquidationParams,\\n uint256 removeLimitOrderFee,\\n uint256 minimumOrderNotional,\\n uint256 minRequiredMargin\\n ) external;\\n\\n /// @notice withdraws protocol fees collected in the supplied wrappers to team multisig\\n /// @param numberOfPoolsToUpdateInThisTx number of pools to collect fees from\\n function withdrawProtocolFee(uint256 numberOfPoolsToUpdateInThisTx) external;\\n}\\n\",\"keccak256\":\"0x1aad0d196e372bca92b21b75013916fea6fdfd74ea000b9909cc4aa305364642\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseStructures.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { IOracle } from '../IOracle.sol';\\nimport { IVToken } from '../IVToken.sol';\\nimport { IVPoolWrapper } from '../IVPoolWrapper.sol';\\n\\nimport { IClearingHouseEnums } from './IClearingHouseEnums.sol';\\n\\ninterface IClearingHouseStructures is IClearingHouseEnums {\\n struct BalanceAdjustments {\\n int256 vQuoteIncrease; // specifies the increase in vQuote balance\\n int256 vTokenIncrease; // specifies the increase in token balance\\n int256 traderPositionIncrease; // specifies the increase in trader position\\n }\\n\\n struct Collateral {\\n IERC20 token; // address of the collateral token\\n CollateralSettings settings; // collateral settings, changable by governance later\\n }\\n\\n struct CollateralSettings {\\n IOracle oracle; // address of oracle which gives price to be used for collateral\\n uint32 twapDuration; // duration of the twap in seconds\\n bool isAllowedForDeposit; // whether the collateral is allowed to be deposited at the moment\\n }\\n\\n struct CollateralDepositView {\\n IERC20 collateral; // address of the collateral token\\n uint256 balance; // balance of the collateral in the account\\n }\\n\\n struct LiquidityChangeParams {\\n int24 tickLower; // tick lower of the range\\n int24 tickUpper; // tick upper of the range\\n int128 liquidityDelta; // positive to add liquidity, negative to remove liquidity\\n uint160 sqrtPriceCurrent; // hint for virtual price, to prevent sandwitch attack\\n uint16 slippageToleranceBps; // slippage tolerance in bps, to prevent sandwitch attack\\n bool closeTokenPosition; // whether to close the token position generated due to the liquidity change\\n LimitOrderType limitOrderType; // limit order type\\n bool settleProfit; // whether to settle profit against USDC margin\\n }\\n\\n struct LiquidityPositionView {\\n int24 tickLower; // tick lower of the range\\n int24 tickUpper; // tick upper of the range\\n uint128 liquidity; // liquidity in the range by the account\\n int256 vTokenAmountIn; // amount of token supplied by the account, to calculate net position\\n int256 sumALastX128; // checkpoint of the term A in funding payment math\\n int256 sumBInsideLastX128; // checkpoint of the term B in funding payment math\\n int256 sumFpInsideLastX128; // checkpoint of the term Fp in funding payment math\\n uint256 sumFeeInsideLastX128; // checkpoint of the trading fees\\n LimitOrderType limitOrderType; // limit order type\\n }\\n\\n struct LiquidationParams {\\n uint16 rangeLiquidationFeeFraction; // fraction of net token position rm from the range to be charged as liquidation fees (in 1e5)\\n uint16 tokenLiquidationFeeFraction; // fraction of traded amount of vquote to be charged as liquidation fees (in 1e5)\\n uint16 closeFactorMMThresholdBps; // fraction the MM threshold for partial liquidation (in 1e4)\\n uint16 partialLiquidationCloseFactorBps; // fraction the % of position to be liquidated if partial liquidation should occur (in 1e4)\\n uint16 insuranceFundFeeShareBps; // fraction of the fee share for insurance fund out of the total liquidation fee (in 1e4)\\n uint16 liquidationSlippageSqrtToleranceBps; // fraction of the max sqrt price slippage threshold (in 1e4) (can be set to - actual price slippage tolerance / 2)\\n uint64 maxRangeLiquidationFees; // maximum range liquidation fees (in settlement token amount decimals)\\n uint64 minNotionalLiquidatable; // minimum notional value of position for it to be eligible for partial liquidation (in settlement token amount decimals)\\n }\\n\\n struct MulticallOperation {\\n MulticallOperationType operationType; // operation type\\n bytes data; // abi encoded data for the operation\\n }\\n\\n struct Pool {\\n IVToken vToken; // address of the vToken, poolId = vToken.truncate()\\n IUniswapV3Pool vPool; // address of the UniswapV3Pool(token0=vToken, token1=vQuote, fee=500)\\n IVPoolWrapper vPoolWrapper; // wrapper address\\n PoolSettings settings; // pool settings, which can be updated by governance later\\n }\\n\\n struct PoolSettings {\\n uint16 initialMarginRatioBps; // margin ratio (1e4) considered for create/update position, removing margin or profit\\n uint16 maintainanceMarginRatioBps; // margin ratio (1e4) considered for liquidations by keeper\\n uint16 maxVirtualPriceDeviationRatioBps; // maximum deviation (1e4) from the current virtual price\\n uint32 twapDuration; // twap duration (seconds) for oracle\\n bool isAllowedForTrade; // whether the pool is allowed to be traded at the moment\\n bool isCrossMargined; // whether cross margined is done for positions of this pool\\n IOracle oracle; // spot price feed twap oracle for this pool\\n }\\n\\n struct SwapParams {\\n int256 amount; // amount of tokens/vQuote to swap\\n uint160 sqrtPriceLimit; // threshold sqrt price which should not be crossed\\n bool isNotional; // whether the amount represents vQuote amount\\n bool isPartialAllowed; // whether to end swap (partial) when sqrtPriceLimit is reached, instead of reverting\\n bool settleProfit; // whether to settle profit against USDC margin\\n }\\n\\n struct TickRange {\\n int24 tickLower;\\n int24 tickUpper;\\n }\\n\\n struct VTokenPositionView {\\n uint32 poolId; // id of the pool of which this token position is for\\n int256 balance; // vTokenLong - vTokenShort\\n int256 netTraderPosition; // net position due to trades and liquidity change carries\\n int256 sumALastX128; // checkoint of the term A in funding payment math\\n LiquidityPositionView[] liquidityPositions; // liquidity positions of the account in the pool\\n }\\n}\\n\",\"keccak256\":\"0x2898873034245bbb873b239ea1fe46b528897bc0018ccf46c2630f8f50e5cb25\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseSystemActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IInsuranceFund } from '../IInsuranceFund.sol';\\nimport { IOracle } from '../IOracle.sol';\\nimport { IVQuote } from '../IVQuote.sol';\\nimport { IVToken } from '../IVToken.sol';\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseSystemActions is IClearingHouseStructures {\\n /// @notice initializes clearing house contract\\n /// @param rageTradeFactoryAddress rage trade factory address\\n /// @param defaultCollateralToken address of default collateral token\\n /// @param defaultCollateralTokenOracle address of default collateral token oracle\\n /// @param insuranceFund address of insurance fund\\n /// @param vQuote address of vQuote\\n function initialize(\\n address rageTradeFactoryAddress,\\n address initialGovernance,\\n address initialTeamMultisig,\\n IERC20 defaultCollateralToken,\\n IOracle defaultCollateralTokenOracle,\\n IInsuranceFund insuranceFund,\\n IVQuote vQuote\\n ) external;\\n\\n function registerPool(Pool calldata poolInfo) external;\\n}\\n\",\"keccak256\":\"0x55af54c49f58ce14276954987014f03e878933ec0b51dca03e3cd2a2b99bd8d5\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseView.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\nimport { IExtsload } from '../IExtsload.sol';\\n\\ninterface IClearingHouseView is IClearingHouseStructures, IExtsload {\\n /// @notice Gets the market value and required margin of an account\\n /// @dev This method can be used to check if an account is under water or not.\\n /// If accountMarketValue < requiredMargin then liquidation can take place.\\n /// @param accountId the account id\\n /// @param isInitialMargin true is initial margin, false is maintainance margin\\n /// @return accountMarketValue the market value of the account, due to collateral and positions\\n /// @return requiredMargin margin needed due to positions\\n function getAccountMarketValueAndRequiredMargin(uint256 accountId, bool isInitialMargin)\\n external\\n view\\n returns (int256 accountMarketValue, int256 requiredMargin);\\n\\n /// @notice Gets the net profit of an account\\n /// @param accountId the account id\\n /// @return accountNetProfit the net profit of the account\\n function getAccountNetProfit(uint256 accountId) external view returns (int256 accountNetProfit);\\n\\n /// @notice Gets the net position of an account\\n /// @param accountId the account id\\n /// @param poolId the id of the pool (vETH, ... etc)\\n /// @return netPosition the net position of the account\\n function getAccountNetTokenPosition(uint256 accountId, uint32 poolId) external view returns (int256 netPosition);\\n\\n /// @notice Gets the real twap price from the respective oracle of the given poolId\\n /// @param poolId the id of the pool\\n /// @return realPriceX128 the real price of the pool\\n function getRealTwapPriceX128(uint32 poolId) external view returns (uint256 realPriceX128);\\n\\n /// @notice Gets the virtual twap price from the respective oracle of the given poolId\\n /// @param poolId the id of the pool\\n /// @return virtualPriceX128 the virtual price of the pool\\n function getVirtualTwapPriceX128(uint32 poolId) external view returns (uint256 virtualPriceX128);\\n}\\n\",\"keccak256\":\"0xd9810b0098f0bc1999c4116f8125b4b2d20ff675c1f2a75c55dd1406fa6b0ecd\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/Account.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\n\\nimport { AddressHelper } from './AddressHelper.sol';\\nimport { CollateralDeposit } from './CollateralDeposit.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { SignedMath } from './SignedMath.sol';\\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\\nimport { LiquidityPosition } from './LiquidityPosition.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { VTokenPosition } from './VTokenPosition.sol';\\nimport { VTokenPositionSet } from './VTokenPositionSet.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\\nimport { IVQuote } from '../interfaces/IVQuote.sol';\\nimport { IVToken } from '../interfaces/IVToken.sol';\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Cross margined account functions\\n/// @dev This library is deployed and used as an external library by ClearingHouse contract.\\nlibrary Account {\\n using AddressHelper for address;\\n using FullMath for uint256;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n using SignedMath for int256;\\n\\n using Account for Account.Info;\\n using CollateralDeposit for CollateralDeposit.Set;\\n using LiquidityPositionSet for LiquidityPosition.Set;\\n using Protocol for Protocol.Info;\\n using VTokenPosition for VTokenPosition.Info;\\n using VTokenPositionSet for VTokenPosition.Set;\\n\\n /// @notice account info for user\\n /// @param owner specifies the account owner\\n /// @param tokenPositions is set of all open token positions\\n /// @param collateralDeposits is set of all deposits\\n struct Info {\\n uint96 id;\\n address owner;\\n VTokenPosition.Set tokenPositions;\\n CollateralDeposit.Set collateralDeposits;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n /**\\n * Errors\\n */\\n\\n /// @notice error to denote that there is not enough margin for the transaction to go through\\n /// @param accountMarketValue shows the account market value after the transaction is executed\\n /// @param totalRequiredMargin shows the total required margin after the transaction is executed\\n error InvalidTransactionNotEnoughMargin(int256 accountMarketValue, int256 totalRequiredMargin);\\n\\n /// @notice error to denote that there is not enough profit during profit withdrawal\\n /// @param totalProfit shows the value of positions at the time of execution after removing amount specified\\n error InvalidTransactionNotEnoughProfit(int256 totalProfit);\\n\\n /// @notice error to denote that there is enough margin, hence the liquidation is invalid\\n /// @param accountMarketValue shows the account market value before liquidation\\n /// @param totalRequiredMargin shows the total required margin before liquidation\\n error InvalidLiquidationAccountAboveWater(int256 accountMarketValue, int256 totalRequiredMargin);\\n\\n /// @notice error to denote that there are active ranges present during token liquidation, hence the liquidation is invalid\\n /// @param poolId shows the poolId for which range is active\\n error InvalidLiquidationActiveRangePresent(uint32 poolId);\\n\\n /// @notice denotes withdrawal of profit in settlement token\\n /// @param accountId serial number of the account\\n /// @param amount amount of profit withdrawn\\n event ProfitUpdated(uint256 indexed accountId, int256 amount);\\n\\n /**\\n * Events\\n */\\n\\n /// @notice denotes add or remove of margin\\n /// @param accountId serial number of the account\\n /// @param collateralId token in which margin is deposited\\n /// @param amount amount of tokens deposited\\n event MarginUpdated(uint256 indexed accountId, uint32 indexed collateralId, int256 amount, bool isSettleProfit);\\n\\n /// @notice denotes range position liquidation event\\n /// @dev all range positions are liquidated and the current tokens inside the range are added in as token positions to the account\\n /// @param accountId serial number of the account\\n /// @param keeperAddress address of keeper who performed the liquidation\\n /// @param liquidationFee total liquidation fee charged to the account\\n /// @param keeperFee total liquidaiton fee paid to the keeper (positive only)\\n /// @param insuranceFundFee total liquidaiton fee paid to the insurance fund (can be negative in case the account is not enought to cover the fee)\\n event LiquidityPositionsLiquidated(\\n uint256 indexed accountId,\\n address indexed keeperAddress,\\n int256 liquidationFee,\\n int256 keeperFee,\\n int256 insuranceFundFee,\\n int256 accountMarketValueFinal\\n );\\n\\n /// @notice denotes token position liquidation event\\n /// @dev the selected token position is take from the current account and moved to liquidatorAccount at a discounted prive to current pool price\\n /// @param accountId serial number of the account\\n /// @param poolId id of the rage trade pool for whose position was liquidated\\n /// @param keeperFee total liquidaiton fee paid to keeper\\n /// @param insuranceFundFee total liquidaiton fee paid to the insurance fund (can be negative in case the account is not enough to cover the fee)\\n event TokenPositionLiquidated(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int256 keeperFee,\\n int256 insuranceFundFee,\\n int256 accountMarketValueFinal\\n );\\n\\n /**\\n * External methods\\n */\\n\\n /// @notice changes deposit balance of 'vToken' by 'amount'\\n /// @param account account to deposit balance into\\n /// @param collateralId collateral id of the token\\n /// @param amount amount of token to deposit or withdraw\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n function updateMargin(\\n Account.Info storage account,\\n uint32 collateralId,\\n int256 amount,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n ) external {\\n _updateMargin(account, collateralId, amount, protocol, checkMargin, false);\\n }\\n\\n /// @notice updates 'amount' of profit generated in settlement token\\n /// @param account account to remove profit from\\n /// @param amount amount of profit(settlement token) to add/remove\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n function updateProfit(\\n Account.Info storage account,\\n int256 amount,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n ) external {\\n _updateProfit(account, amount, protocol, checkMargin);\\n }\\n\\n function settleProfit(Account.Info storage account, Protocol.Info storage protocol) external {\\n _settleProfit(account, protocol);\\n }\\n\\n /// @notice swaps 'vToken' of token amount equal to 'swapParams.amount'\\n /// @notice if vTokenAmount>0 then the swap is a long or close short and if vTokenAmount<0 then swap is a short or close long\\n /// @notice isNotional specifies whether the amount represents token amount (false) or vQuote amount(true)\\n /// @notice isPartialAllowed specifies whether to revert (false) or to execute a partial swap (true)\\n /// @notice sqrtPriceLimit threshold sqrt price which if crossed then revert or execute partial swap\\n /// @param account account to swap tokens for\\n /// @param poolId id of the pool to swap tokens for\\n /// @param swapParams parameters for the swap (Includes - amount, sqrtPriceLimit, isNotional, isPartialAllowed)\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n /// @return vTokenAmountOut amount of vToken after swap (user receiving then +ve, user paying then -ve)\\n /// @return vQuoteAmountOut amount of vQuote after swap (user receiving then +ve, user paying then -ve)\\n function swapToken(\\n Account.Info storage account,\\n uint32 poolId,\\n IClearingHouseStructures.SwapParams memory swapParams,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n // make a swap. vQuoteIn and vTokenAmountOut (in and out wrt uniswap).\\n // mints erc20 tokens in callback and send to the pool\\n (vTokenAmountOut, vQuoteAmountOut) = account.tokenPositions.swapToken(account.id, poolId, swapParams, protocol);\\n\\n if (swapParams.settleProfit) {\\n account._settleProfit(protocol);\\n }\\n // after all the stuff, account should be above water\\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\\n }\\n\\n /// @notice changes range liquidity 'vToken' of market value equal to 'vTokenNotional'\\n /// @notice if 'liquidityDelta'>0 then liquidity is added and if 'liquidityChange'<0 then liquidity is removed\\n /// @notice the liquidity change is reverted if the sqrt price at the time of execution is beyond 'slippageToleranceBps' of 'sqrtPriceCurrent' supplied\\n /// @notice whenever liquidity change is done the external token position is taken out. If 'closeTokenPosition' is true this is swapped out else it is added to the current token position\\n /// @param account account to change liquidity\\n /// @param poolId id of the rage trade pool\\n /// @param liquidityChangeParams parameters including lower tick, upper tick, liquidity delta, sqrtPriceCurrent, slippageToleranceBps, closeTokenPosition, limit order type\\n /// @param protocol set of all constants and token addresses\\n function liquidityChange(\\n Account.Info storage account,\\n uint32 poolId,\\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n )\\n external\\n returns (\\n int256 vTokenAmountOut,\\n int256 vQuoteAmountOut,\\n uint256 notionalValueAbs\\n )\\n {\\n // mint/burn tokens + fee + funding payment\\n (vTokenAmountOut, vQuoteAmountOut) = account.tokenPositions.liquidityChange(\\n account.id,\\n poolId,\\n liquidityChangeParams,\\n protocol\\n );\\n\\n if (liquidityChangeParams.settleProfit) {\\n account._settleProfit(protocol);\\n }\\n // after all the stuff, account should be above water\\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\\n\\n notionalValueAbs = protocol.getNotionalValue(poolId, vTokenAmountOut, vQuoteAmountOut);\\n }\\n\\n /// @notice liquidates all range positions in case the account is under water\\n /// charges a liquidation fee to the account and pays partially to the insurance fund and rest to the keeper.\\n /// @dev insurance fund covers the remaining fee if the account market value is not enough\\n /// @param account account to liquidate\\n /// @param protocol set of all constants and token addresses\\n /// @return keeperFee amount of liquidation fee paid to keeper\\n /// @return insuranceFundFee amount of liquidation fee paid to insurance fund\\n /// @return accountMarketValue account market value before liquidation\\n function liquidateLiquidityPositions(Account.Info storage account, Protocol.Info storage protocol)\\n external\\n returns (\\n int256 keeperFee,\\n int256 insuranceFundFee,\\n int256 accountMarketValue\\n )\\n {\\n // check basis maintanace margin\\n int256 totalRequiredMargin;\\n uint256 notionalAmountClosed;\\n\\n (accountMarketValue, totalRequiredMargin) = account._getAccountValueAndRequiredMargin(false, protocol);\\n\\n // check and revert if account is above water\\n if (accountMarketValue > totalRequiredMargin) {\\n revert InvalidLiquidationAccountAboveWater(accountMarketValue, totalRequiredMargin);\\n }\\n // liquidate all liquidity positions\\n notionalAmountClosed = account.tokenPositions.liquidateLiquidityPositions(account.id, protocol);\\n\\n // compute liquidation fees\\n (keeperFee, insuranceFundFee) = _computeLiquidationFees(\\n accountMarketValue,\\n notionalAmountClosed,\\n true,\\n protocol.liquidationParams\\n );\\n\\n account._updateVQuoteBalance(-(keeperFee + insuranceFundFee));\\n }\\n\\n /// @notice liquidates token position specified by 'poolId' in case account is underwater\\n /// charges a liquidation fee to the account and pays partially to the insurance fund and rest to the keeper.\\n /// @dev closes position uptil a specified slippage threshold in protocol.liquidationParams\\n /// @dev insurance fund covers the remaining fee if the account market value is not enough\\n /// @dev if there is range position this reverts (liquidators are supposed to liquidate range positions first)\\n /// @param account account to liquidate\\n /// @param poolId id of the pool to liquidate\\n /// @param protocol set of all constants and token addresses\\n /// @return keeperFee amount of liquidation fee paid to keeper\\n /// @return insuranceFundFee amount of liquidation fee paid to insurance fund\\n function liquidateTokenPosition(\\n Account.Info storage account,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) external returns (int256 keeperFee, int256 insuranceFundFee) {\\n bool isPartialLiquidation;\\n\\n // check if there is range position and revert\\n if (account.tokenPositions.isTokenRangeActive(poolId)) revert InvalidLiquidationActiveRangePresent(poolId);\\n\\n {\\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\\n false,\\n protocol\\n );\\n\\n // check and revert if account is above water\\n if (accountMarketValue > totalRequiredMargin) {\\n revert InvalidLiquidationAccountAboveWater(accountMarketValue, totalRequiredMargin);\\n } else if (\\n // check if account is underwater but within partial liquidation threshold\\n accountMarketValue >\\n totalRequiredMargin.mulDiv(protocol.liquidationParams.closeFactorMMThresholdBps, 1e4)\\n ) {\\n isPartialLiquidation = true;\\n }\\n }\\n\\n int256 tokensToTrade;\\n {\\n // get the net token position and tokensToTrade = -tokenPosition\\n // since no ranges are supposed to be there so only tokenPosition is in vTokenPositionSet\\n VTokenPosition.Info storage vTokenPosition = account.tokenPositions.getTokenPosition(poolId, false);\\n tokensToTrade = -vTokenPosition.balance;\\n uint256 tokenNotionalValue = tokensToTrade.absUint().mulDiv(\\n protocol.getCachedVirtualTwapPriceX128(poolId),\\n FixedPoint128.Q128\\n );\\n\\n // check if the token position is less than a certain notional value\\n // if so then liquidate the whole position even if partial liquidation is allowed\\n // otherwise do partial liquidation\\n if (isPartialLiquidation && tokenNotionalValue > protocol.liquidationParams.minNotionalLiquidatable) {\\n tokensToTrade = tokensToTrade.mulDiv(protocol.liquidationParams.partialLiquidationCloseFactorBps, 1e4);\\n }\\n }\\n\\n int256 accountMarketValueFinal;\\n {\\n uint160 sqrtPriceLimit;\\n {\\n // calculate sqrt price limit based on slippage threshold\\n uint160 sqrtTwapPrice = protocol.getVirtualTwapSqrtPriceX96(poolId);\\n if (tokensToTrade > 0) {\\n sqrtPriceLimit = uint256(sqrtTwapPrice)\\n .mulDiv(1e4 + protocol.liquidationParams.liquidationSlippageSqrtToleranceBps, 1e4)\\n .toUint160();\\n } else {\\n sqrtPriceLimit = uint256(sqrtTwapPrice)\\n .mulDiv(1e4 - protocol.liquidationParams.liquidationSlippageSqrtToleranceBps, 1e4)\\n .toUint160();\\n }\\n }\\n\\n // close position uptil sqrt price limit\\n (, int256 vQuoteAmountSwapped) = account.tokenPositions.swapToken(\\n account.id,\\n poolId,\\n IClearingHouseStructures.SwapParams({\\n amount: tokensToTrade,\\n sqrtPriceLimit: sqrtPriceLimit,\\n isNotional: false,\\n isPartialAllowed: true,\\n settleProfit: false\\n }),\\n protocol\\n );\\n\\n // get the account market value after closing the position\\n accountMarketValueFinal = account._getAccountValue(protocol);\\n\\n // compute liquidation fees\\n (keeperFee, insuranceFundFee) = _computeLiquidationFees(\\n accountMarketValueFinal,\\n vQuoteAmountSwapped.absUint(),\\n false,\\n protocol.liquidationParams\\n );\\n }\\n\\n // deduct liquidation fees from account\\n account._updateVQuoteBalance(-(keeperFee + insuranceFundFee));\\n\\n emit TokenPositionLiquidated(account.id, poolId, keeperFee, insuranceFundFee, accountMarketValueFinal);\\n }\\n\\n /// @notice removes limit order based on the current price position (keeper call)\\n /// @param account account to liquidate\\n /// @param poolId id of the pool for the range\\n /// @param tickLower lower tick index for the range\\n /// @param tickUpper upper tick index for the range\\n /// @param protocol platform constants\\n function removeLimitOrder(\\n Account.Info storage account,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n uint256 limitOrderFee,\\n Protocol.Info storage protocol\\n ) external {\\n account.tokenPositions.removeLimitOrder(account.id, poolId, tickLower, tickUpper, protocol);\\n\\n account._updateVQuoteBalance(-int256(limitOrderFee));\\n }\\n\\n /**\\n * External view methods\\n */\\n\\n /// @notice returns market value for the account positions based on current market conditions\\n /// @param account account to check\\n /// @param protocol set of all constants and token addresses\\n /// @return accountPositionProfits total market value of all the positions (token ) and deposits\\n function getAccountPositionProfits(Account.Info storage account, Protocol.Info storage protocol)\\n external\\n view\\n returns (int256 accountPositionProfits)\\n {\\n return account._getAccountPositionProfits(protocol);\\n }\\n\\n /// @notice returns market value and required margin for the account based on current market conditions\\n /// @dev (In case requiredMargin < minRequiredMargin then requiredMargin = minRequiredMargin)\\n /// @param account account to check\\n /// @param isInitialMargin true to use initial margin factor and false to use maintainance margin factor for calcualtion of required margin\\n /// @param protocol set of all constants and token addresses\\n /// @return accountMarketValue total market value of all the positions (token ) and deposits\\n /// @return totalRequiredMargin total margin required to keep the account above selected margin requirement (intial/maintainance)\\n function getAccountValueAndRequiredMargin(\\n Account.Info storage account,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) external view returns (int256 accountMarketValue, int256 totalRequiredMargin) {\\n return account._getAccountValueAndRequiredMargin(isInitialMargin, protocol);\\n }\\n\\n /// @notice checks if market value > required margin else revert with InvalidTransactionNotEnoughMargin\\n /// @param account account to check\\n /// @param isInitialMargin true to use initialMarginFactor and false to use maintainance margin factor for calcualtion of required margin\\n /// @param protocol set of all constants and token addresses\\n function checkIfMarginAvailable(\\n Account.Info storage account,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) external view {\\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\\n isInitialMargin,\\n protocol\\n );\\n if (accountMarketValue < totalRequiredMargin)\\n revert InvalidTransactionNotEnoughMargin(accountMarketValue, totalRequiredMargin);\\n }\\n\\n /// @notice checks if profit is available to withdraw settlement token (token value of all positions > 0) else revert with InvalidTransactionNotEnoughProfit\\n /// @param account account to check\\n /// @param protocol set of all constants and token addresses\\n function checkIfProfitAvailable(Account.Info storage account, Protocol.Info storage protocol) external view {\\n _checkIfProfitAvailable(account, protocol);\\n }\\n\\n /// @notice gets information about all the collateral and positions in the account\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n /// @return owner of the account\\n /// @return vQuoteBalance amount of vQuote in the account\\n /// @return collateralDeposits list of all the collateral amounts\\n /// @return tokenPositions list of all the token and liquidity positions\\n function getInfo(Account.Info storage account, Protocol.Info storage protocol)\\n external\\n view\\n returns (\\n address owner,\\n int256 vQuoteBalance,\\n IClearingHouseStructures.CollateralDepositView[] memory collateralDeposits,\\n IClearingHouseStructures.VTokenPositionView[] memory tokenPositions\\n )\\n {\\n owner = account.owner;\\n collateralDeposits = account.collateralDeposits.getInfo(protocol);\\n (vQuoteBalance, tokenPositions) = account.tokenPositions.getInfo();\\n }\\n\\n /// @notice gets the net position of the account for a given pool\\n /// @param account ref to the account state\\n /// @param poolId id of the pool\\n /// @param protocol ref to the protocol state\\n /// @return netPosition net position of the account for the pool\\n function getNetPosition(\\n Account.Info storage account,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) external view returns (int256 netPosition) {\\n return account.tokenPositions.getNetPosition(poolId, protocol);\\n }\\n\\n /**\\n * Internal methods\\n */\\n\\n function updateAccountPoolPrices(Account.Info storage account, Protocol.Info storage protocol) internal {\\n account.tokenPositions.updateOpenPoolPrices(protocol);\\n }\\n\\n /// @notice settles profit or loss for the account\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n function _settleProfit(Account.Info storage account, Protocol.Info storage protocol) internal {\\n int256 profits = account._getAccountPositionProfits(protocol);\\n uint32 settlementCollateralId = AddressHelper.truncate(protocol.settlementToken);\\n if (profits > 0) {\\n account._updateProfit(-profits, protocol, false);\\n account._updateMargin({\\n collateralId: settlementCollateralId,\\n amount: profits,\\n protocol: protocol,\\n checkMargin: false,\\n isSettleProfit: true\\n });\\n } else if (profits < 0) {\\n uint256 balance = account.collateralDeposits.getBalance(settlementCollateralId);\\n uint256 profitAbsUint = uint256(-profits);\\n uint256 balanceToUpdate = balance > profitAbsUint ? profitAbsUint : balance;\\n if (balanceToUpdate > 0) {\\n account._updateMargin({\\n collateralId: settlementCollateralId,\\n amount: -balanceToUpdate.toInt256(),\\n protocol: protocol,\\n checkMargin: false,\\n isSettleProfit: true\\n });\\n account._updateProfit(balanceToUpdate.toInt256(), protocol, false);\\n }\\n }\\n }\\n\\n /// @notice updates 'amount' of profit generated in settlement token\\n /// @param account account to remove profit from\\n /// @param amount amount of profit(settlement token) to add/remove\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n function _updateProfit(\\n Account.Info storage account,\\n int256 amount,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n ) internal {\\n account._updateVQuoteBalance(amount);\\n\\n if (checkMargin && amount < 0) {\\n account._checkIfProfitAvailable(protocol);\\n account._checkIfMarginAvailable(true, protocol);\\n }\\n\\n emit ProfitUpdated(account.id, amount);\\n }\\n\\n /// @notice changes deposit balance of 'vToken' by 'amount'\\n /// @param account account to deposit balance into\\n /// @param collateralId collateral id of the token\\n /// @param amount amount of token to deposit or withdraw\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n function _updateMargin(\\n Account.Info storage account,\\n uint32 collateralId,\\n int256 amount,\\n Protocol.Info storage protocol,\\n bool checkMargin,\\n bool isSettleProfit\\n ) internal {\\n if (amount > 0) {\\n account.collateralDeposits.increaseBalance(collateralId, uint256(amount));\\n } else {\\n account.collateralDeposits.decreaseBalance(collateralId, uint256(-amount));\\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\\n }\\n\\n emit MarginUpdated(account.id, collateralId, amount, isSettleProfit);\\n }\\n\\n /// @notice updates the vQuote balance for 'account' by 'amount'\\n /// @param account pointer to 'account' struct\\n /// @param amount amount of balance to update\\n /// @return balanceAdjustments vToken and vQuote balance changes of the account\\n function _updateVQuoteBalance(Account.Info storage account, int256 amount)\\n internal\\n returns (IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments)\\n {\\n balanceAdjustments = IClearingHouseStructures.BalanceAdjustments(amount, 0, 0);\\n account.tokenPositions.vQuoteBalance += balanceAdjustments.vQuoteIncrease;\\n }\\n\\n /**\\n * Internal view methods\\n */\\n\\n /// @notice ensures that the account has enough margin to cover the required margin\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n function _checkIfMarginAvailable(\\n Account.Info storage account,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) internal view {\\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\\n isInitialMargin,\\n protocol\\n );\\n if (accountMarketValue < totalRequiredMargin)\\n revert InvalidTransactionNotEnoughMargin(accountMarketValue, totalRequiredMargin);\\n }\\n\\n /// @notice ensures that the account has non negative profit\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n function _checkIfProfitAvailable(Account.Info storage account, Protocol.Info storage protocol) internal view {\\n int256 totalPositionValue = account._getAccountPositionProfits(protocol);\\n if (totalPositionValue < 0) revert InvalidTransactionNotEnoughProfit(totalPositionValue);\\n }\\n\\n /// @notice gets the amount of account's position profits\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n function _getAccountPositionProfits(Account.Info storage account, Protocol.Info storage protocol)\\n internal\\n view\\n returns (int256 accountPositionProfits)\\n {\\n accountPositionProfits = account.tokenPositions.getAccountMarketValue(protocol);\\n }\\n\\n /// @notice gets market value for the account based on current market conditions\\n /// @param account ref to the account state\\n /// @param protocol set of all constants and token addresses\\n /// @return accountMarketValue total market value of all the positions (token ) and deposits\\n function _getAccountValue(Account.Info storage account, Protocol.Info storage protocol)\\n internal\\n view\\n returns (int256 accountMarketValue)\\n {\\n accountMarketValue = account._getAccountPositionProfits(protocol);\\n accountMarketValue += account.collateralDeposits.marketValue(protocol);\\n return (accountMarketValue);\\n }\\n\\n /// @notice gets market value and req margin for the account based on current market conditions\\n /// @param account ref to the account state\\n /// @param isInitialMargin true to use initialMarginFactor and false to use maintainance margin factor for calcualtion of required margin\\n /// @param protocol set of all constants and token addresses\\n /// @return accountMarketValue total market value of all the positions (token) and deposits\\n /// @return totalRequiredMargin total required margin for the account\\n function _getAccountValueAndRequiredMargin(\\n Account.Info storage account,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 accountMarketValue, int256 totalRequiredMargin) {\\n accountMarketValue = account._getAccountValue(protocol);\\n\\n totalRequiredMargin = account.tokenPositions.getRequiredMargin(isInitialMargin, protocol);\\n if (!account.tokenPositions.isEmpty()) {\\n totalRequiredMargin = totalRequiredMargin < int256(protocol.minRequiredMargin)\\n ? int256(protocol.minRequiredMargin)\\n : totalRequiredMargin;\\n }\\n return (accountMarketValue, totalRequiredMargin);\\n }\\n\\n /// @notice checks if 'account' is initialized\\n /// @param account pointer to 'account' struct\\n function _isInitialized(Account.Info storage account) internal view returns (bool) {\\n return !account.owner.isZero();\\n }\\n\\n /**\\n * Internal pure methods\\n */\\n\\n /// @notice computes keeper fee and insurance fund fee in case of liquidity position liquidation\\n /// @dev keeperFee = liquidationFee*(1-insuranceFundFeeShare)\\n /// @dev insuranceFundFee = accountMarketValue - keeperFee (if accountMarketValue is not enough to cover the fees) else insurancFundFee = liquidationFee - keeperFee\\n /// @param accountMarketValue market value of account\\n /// @param notionalAmountClosed notional value of position closed\\n /// @param isRangeLiquidation - true for range liquidation and false for token liquidation\\n /// @param liquidationParams parameters including insuranceFundFeeShareBps\\n /// @return keeperFee map of vTokens allowed on the platform\\n /// @return insuranceFundFee poolwrapper for token\\n function _computeLiquidationFees(\\n int256 accountMarketValue,\\n uint256 notionalAmountClosed,\\n bool isRangeLiquidation,\\n IClearingHouseStructures.LiquidationParams memory liquidationParams\\n ) internal pure returns (int256 keeperFee, int256 insuranceFundFee) {\\n uint256 liquidationFee;\\n\\n if (isRangeLiquidation) {\\n liquidationFee = notionalAmountClosed.mulDiv(liquidationParams.rangeLiquidationFeeFraction, 1e5);\\n if (liquidationParams.maxRangeLiquidationFees < liquidationFee)\\n liquidationFee = liquidationParams.maxRangeLiquidationFees;\\n } else {\\n liquidationFee = notionalAmountClosed.mulDiv(liquidationParams.tokenLiquidationFeeFraction, 1e5);\\n }\\n\\n int256 liquidationFeeInt = liquidationFee.toInt256();\\n\\n keeperFee = liquidationFeeInt.mulDiv(1e4 - liquidationParams.insuranceFundFeeShareBps, 1e4);\\n if (accountMarketValue - liquidationFeeInt < 0) {\\n insuranceFundFee = accountMarketValue - keeperFee;\\n } else {\\n insuranceFundFee = liquidationFeeInt - keeperFee;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x64e2fafb0b8e346baded62ab407edea1bcc6526bb35a1edadd9a79fcf02f7706\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/AddressHelper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IVToken } from '../interfaces/IVToken.sol';\\n\\n/// @title Address helper functions\\nlibrary AddressHelper {\\n /// @notice converts address to uint32, using the least significant 32 bits\\n /// @param addr Address to convert\\n /// @return truncated last 4 bytes of the address\\n function truncate(address addr) internal pure returns (uint32 truncated) {\\n assembly {\\n truncated := and(addr, 0xffffffff)\\n }\\n }\\n\\n /// @notice converts IERC20 contract to uint32\\n /// @param addr contract\\n /// @return truncated last 4 bytes of the address\\n function truncate(IERC20 addr) internal pure returns (uint32 truncated) {\\n return truncate(address(addr));\\n }\\n\\n /// @notice checks if two addresses are equal\\n /// @param a first address\\n /// @param b second address\\n /// @return true if addresses are equal\\n function eq(address a, address b) internal pure returns (bool) {\\n return a == b;\\n }\\n\\n /// @notice checks if addresses of two IERC20 contracts are equal\\n /// @param a first contract\\n /// @param b second contract\\n /// @return true if addresses are equal\\n function eq(IERC20 a, IERC20 b) internal pure returns (bool) {\\n return eq(address(a), address(b));\\n }\\n\\n /// @notice checks if an address is zero\\n /// @param a address to check\\n /// @return true if address is zero\\n function isZero(address a) internal pure returns (bool) {\\n return a == address(0);\\n }\\n\\n /// @notice checks if address of an IERC20 contract is zero\\n /// @param a contract to check\\n /// @return true if address is zero\\n function isZero(IERC20 a) internal pure returns (bool) {\\n return isZero(address(a));\\n }\\n}\\n\",\"keccak256\":\"0xe4a82de57fe35749b5baf34991cea5356c55dc015d58514a758adafe28af8686\",\"license\":\"MIT\"},\"contracts/libraries/BatchedLoop.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { Math } from '@openzeppelin/contracts/utils/math/Math.sol';\\n\\n/// @title Batched Loop Library\\n/// @notice Aids to perform a lengthy loop in seperate txs\\nlibrary BatchedLoop {\\n uint256 constant NULL = 0;\\n\\n struct Info {\\n uint256 progress; // of array element to resume the progress from\\n }\\n\\n /// @notice Resumes the loop from where it left of previously\\n /// @param loop: the loop object to resume (this is storage ref and val is mutated)\\n /// @param startAt: the index to start from\\n /// @param endBefore: the index to end at\\n /// @param batchSize: number of iterations to perform in this batch\\n /// @param execute: the function to execute for each iteration\\n /// @dev translates to: for(uint i = startAt; i < endBefore; i++) { execute(i); }\\n function iterate(\\n BatchedLoop.Info storage loop,\\n uint256 startAt,\\n uint256 endBefore,\\n uint256 batchSize,\\n function(uint256) execute\\n ) internal returns (bool completed) {\\n // resume the loop from the stored progress else use startAt\\n uint256 from = loop.progress;\\n if (from == NULL) from = startAt;\\n\\n // use endBefore if batchSize is zero, else calculate end index\\n uint256 to = batchSize == NULL ? endBefore : Math.min(from + batchSize, endBefore);\\n\\n // executes upto (to - 1)\\n while (from < to) {\\n execute(from);\\n from++;\\n }\\n\\n if (completed = (to == endBefore)) {\\n // if loop was completed then reset the progress\\n loop.progress = NULL;\\n } else {\\n // store the progress if partial execution of the loop\\n loop.progress = to;\\n }\\n }\\n\\n /// @notice Checks if the loop is in progress\\n /// @param loop: the loop object\\n /// @return true if the loop is in progress else false\\n function isInProgress(BatchedLoop.Info storage loop) internal view returns (bool) {\\n return loop.progress != NULL;\\n }\\n}\\n\",\"keccak256\":\"0xd3a852c38f34d78ba8a17f9d48f3b2f4410c779c4cd05db57b4563d5c6b391d2\",\"license\":\"MIT\"},\"contracts/libraries/Bisection.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\n/// @title Bisection Method\\n/// @notice https://en.wikipedia.org/wiki/Bisection_method\\nlibrary Bisection {\\n error SolutionOutOfBounds(uint256 y_target, uint160 x_lower, uint160 x_upper);\\n\\n /// @notice Finds the solution to the equation f(x) = y_target using the bisection method\\n /// @param f: strictly increasing function f: uint160 -> uint256\\n /// @param y_target: the target value of f(x)\\n /// @param x_lower: the lower bound for x\\n /// @param x_upper: the upper bound for x\\n /// @return x_target: the rounded down solution to the equation f(x) = y_target\\n function findSolution(\\n function(uint160) pure returns (uint256) f,\\n uint256 y_target,\\n uint160 x_lower,\\n uint160 x_upper\\n ) internal pure returns (uint160) {\\n // compute y at the bounds\\n uint256 y_lower = f(x_lower);\\n uint256 y_upper = f(x_upper);\\n\\n // if y is out of the bounds then revert\\n if (y_target < y_lower || y_target > y_upper) revert SolutionOutOfBounds(y_target, x_lower, x_upper);\\n\\n // bisect repeatedly until the solution is within an error of 1 unit\\n uint256 y_mid;\\n uint160 x_mid;\\n while (x_upper - x_lower > 1) {\\n x_mid = x_lower + (x_upper - x_lower) / 2;\\n y_mid = f(x_mid);\\n if (y_mid > y_target) {\\n x_upper = x_mid;\\n y_upper = y_mid;\\n } else {\\n x_lower = x_mid;\\n y_lower = y_mid;\\n }\\n }\\n\\n // at this point, x_upper - x_lower is either 0 or 1\\n // if it is 1 then check if x_upper is the solution, else return x_lower as the rounded down solution\\n return x_lower != x_upper && f(x_upper) == y_target ? x_upper : x_lower;\\n }\\n}\\n\",\"keccak256\":\"0xae30dfb5c8806a894fd086f494cd19bb7019c8bc865522b5ec407b7d71b8e4bc\",\"license\":\"MIT\"},\"contracts/libraries/Block.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ArbSys {\\n /**\\n * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)\\n * @return block number as int\\n */\\n function arbBlockNumber() external view returns (uint256);\\n}\\n\\n/// @title Library for getting block number for the current chain\\nlibrary Block {\\n /// @notice Get block number\\n /// @return block number as uint32\\n function number() internal view returns (uint32) {\\n uint256 chainId = block.chainid;\\n if (chainId == 42161 || chainId == 421611 || chainId == 421612) {\\n return uint32(ArbSys(address(100)).arbBlockNumber());\\n } else {\\n return uint32(block.number);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x19d3884d36aa0f25572b23843633a8b018509e37c7b75852b163a94cfc3aca4a\",\"license\":\"MIT\"},\"contracts/libraries/CollateralDeposit.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\n\\nimport { Protocol } from './Protocol.sol';\\nimport { AddressHelper } from './AddressHelper.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { Uint32L8ArrayLib } from './Uint32L8Array.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\n\\n/// @title Collateral deposit set functions\\nlibrary CollateralDeposit {\\n using AddressHelper for address;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n using Uint32L8ArrayLib for uint32[8];\\n\\n error InsufficientCollateralBalance();\\n\\n struct Set {\\n // Fixed length array of collateralId = collateralAddress.truncate()\\n // Supports upto 8 different collaterals in an account.\\n // Collision is possible, i.e. collateralAddress1.truncate() == collateralAddress2.truncate()\\n // However the possibility is 1/2**32, which is negligible.\\n // There are checks that prevent use of a different collateralAddress for a given collateralId.\\n // If there is a geniune collision, a wrapper for the ERC20 token can deployed such that\\n // there are no collisions with wrapper and the wrapped ERC20 can be used as collateral.\\n uint32[8] active; // array of collateralIds\\n mapping(uint32 => uint256) deposits; // collateralId => deposit amount\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n function getBalance(CollateralDeposit.Set storage set, uint32 collateralId) internal view returns (uint256) {\\n return set.deposits[collateralId];\\n }\\n\\n /// @notice Increase the deposit amount of a given collateralId\\n /// @param set CollateralDepositSet of the account\\n /// @param collateralId The collateralId of the collateral to increase the deposit amount of\\n /// @param amount The amount to increase the deposit amount of the collateral by\\n function increaseBalance(\\n CollateralDeposit.Set storage set,\\n uint32 collateralId,\\n uint256 amount\\n ) internal {\\n set.active.include(collateralId);\\n\\n set.deposits[collateralId] += amount;\\n }\\n\\n /// @notice Decrease the deposit amount of a given collateralId\\n /// @param set CollateralDepositSet of the account\\n /// @param collateralId The collateralId of the collateral to decrease the deposit amount of\\n /// @param amount The amount to decrease the deposit amount of the collateral by\\n function decreaseBalance(\\n CollateralDeposit.Set storage set,\\n uint32 collateralId,\\n uint256 amount\\n ) internal {\\n if (set.deposits[collateralId] < amount) revert InsufficientCollateralBalance();\\n set.deposits[collateralId] -= amount;\\n\\n if (set.deposits[collateralId] == 0) {\\n set.active.exclude(collateralId);\\n }\\n }\\n\\n /// @notice Get the market value of all the collateral deposits in settlementToken denomination\\n /// @param set CollateralDepositSet of the account\\n /// @param protocol Global protocol state\\n /// @return The market value of all the collateral deposits in settlementToken denomination\\n function marketValue(CollateralDeposit.Set storage set, Protocol.Info storage protocol)\\n internal\\n view\\n returns (int256)\\n {\\n int256 accountMarketValue;\\n for (uint8 i = 0; i < set.active.length; i++) {\\n uint32 collateralId = set.active[i];\\n\\n if (collateralId == 0) break;\\n IClearingHouseStructures.Collateral storage collateral = protocol.collaterals[collateralId];\\n\\n accountMarketValue += set.deposits[collateralId].toInt256().mulDiv(\\n collateral.settings.oracle.getTwapPriceX128(collateral.settings.twapDuration),\\n FixedPoint128.Q128\\n );\\n }\\n return accountMarketValue;\\n }\\n\\n /// @notice Get information about all the collateral deposits\\n /// @param set CollateralDepositSet of the account\\n /// @param protocol Global protocol state\\n /// @return collateralDeposits Information about all the collateral deposits\\n function getInfo(CollateralDeposit.Set storage set, Protocol.Info storage protocol)\\n internal\\n view\\n returns (IClearingHouseStructures.CollateralDepositView[] memory collateralDeposits)\\n {\\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\\n collateralDeposits = new IClearingHouseStructures.CollateralDepositView[](numberOfTokenPositions);\\n\\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\\n collateralDeposits[i].collateral = protocol.collaterals[set.active[i]].token;\\n collateralDeposits[i].balance = set.deposits[set.active[i]];\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa0444f3ae1a5555e1d31ab25d0df8e61d4760295c325ae63ca244efc72dede99\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/FundingPayment.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\n\\nimport { SafeCast } from './SafeCast.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\n\\n/// @title Funding payment functions\\n/// @notice Funding Payment Logic used to distribute the FP bill paid by traders among the LPs in the liquidity range\\nlibrary FundingPayment {\\n using FullMath for uint256;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n\\n struct Info {\\n // FR * P * dt\\n int256 sumAX128;\\n // trade token amount / liquidity\\n int256 sumBX128;\\n // sum(a * sumB)\\n int256 sumFpX128;\\n // time when state was last updated\\n uint48 timestampLast;\\n }\\n\\n event FundingPaymentStateUpdated(\\n FundingPayment.Info fundingPayment,\\n int256 fundingRateX128,\\n uint256 virtualPriceX128\\n );\\n\\n /// @notice Calculates the funding rate based on prices\\n /// @param realPriceX128 spot price of token\\n /// @param virtualPriceX128 futures price of token\\n function getFundingRate(uint256 realPriceX128, uint256 virtualPriceX128)\\n internal\\n pure\\n returns (int256 fundingRateX128)\\n {\\n int256 priceDeltaX128 = virtualPriceX128.toInt256() - realPriceX128.toInt256();\\n return priceDeltaX128.mulDiv(FixedPoint128.Q128, realPriceX128) / 1 days;\\n }\\n\\n /// @notice Used to update the state of the funding payment whenever a trade takes place\\n /// @param info pointer to the funding payment state\\n /// @param vTokenAmount trade token amount\\n /// @param liquidity active liquidity in the range during the trade (step)\\n /// @param blockTimestamp timestamp of current block\\n /// @param fundingRateX128 the constant funding rate to apply for the duration between timestampLast and blockTimestamp\\n /// @param virtualPriceX128 futures price of token\\n function update(\\n FundingPayment.Info storage info,\\n int256 vTokenAmount,\\n uint256 liquidity,\\n uint48 blockTimestamp,\\n int256 fundingRateX128,\\n uint256 virtualPriceX128\\n ) internal {\\n int256 a = nextAX128(info.timestampLast, blockTimestamp, fundingRateX128, virtualPriceX128);\\n info.sumFpX128 += a.mulDivRoundingDown(info.sumBX128, int256(FixedPoint128.Q128));\\n info.sumAX128 += a;\\n info.sumBX128 += vTokenAmount.mulDiv(int256(FixedPoint128.Q128), int256(liquidity));\\n info.timestampLast = blockTimestamp;\\n\\n emit FundingPaymentStateUpdated(info, fundingRateX128, virtualPriceX128);\\n }\\n\\n /// @notice Used to get the rate of funding payment for the duration between last trade and this trade\\n /// @dev Positive A value means at this duration, longs pay shorts. Negative means shorts pay longs.\\n /// @param timestampLast start timestamp of duration\\n /// @param blockTimestamp end timestamp of duration\\n /// @param virtualPriceX128 futures price of token\\n /// @param fundingRateX128 the constant funding rate to apply for the duration between timestampLast and blockTimestamp\\n /// @return aX128 value called \\\"a\\\" (see funding payment math documentation)\\n function nextAX128(\\n uint48 timestampLast,\\n uint48 blockTimestamp,\\n int256 fundingRateX128,\\n uint256 virtualPriceX128\\n ) internal pure returns (int256 aX128) {\\n return fundingRateX128.mulDiv(virtualPriceX128, FixedPoint128.Q128) * int48(blockTimestamp - timestampLast);\\n }\\n\\n function extrapolatedSumAX128(\\n int256 sumAX128,\\n uint48 timestampLast,\\n uint48 blockTimestamp,\\n int256 fundingRateX128,\\n uint256 virtualPriceX128\\n ) internal pure returns (int256) {\\n return sumAX128 + nextAX128(timestampLast, blockTimestamp, fundingRateX128, virtualPriceX128);\\n }\\n\\n /// @notice Extrapolates (updates) the value of sumFp by adding the missing component to it using sumAGlobalX128\\n /// @param sumAX128 sumA value that is recorded from global at some point in time\\n /// @param sumBX128 sumB value that is recorded from global at same point in time as sumA\\n /// @param sumFpX128 sumFp value that is recorded from global at same point in time as sumA and sumB\\n /// @param sumAGlobalX128 latest sumA value (taken from global), used to extrapolate the sumFp\\n function extrapolatedSumFpX128(\\n int256 sumAX128,\\n int256 sumBX128,\\n int256 sumFpX128,\\n int256 sumAGlobalX128\\n ) internal pure returns (int256) {\\n return sumFpX128 + sumBX128.mulDiv(sumAGlobalX128 - sumAX128, int256(FixedPoint128.Q128));\\n }\\n\\n /// @notice Positive bill is charged from LPs, Negative bill is rewarded to LPs\\n /// @param sumAX128 latest value of sumA (to be taken from global state)\\n /// @param sumFpInsideX128 latest value of sumFp inside range (to be computed using global state + tick state)\\n /// @param sumALastX128 value of sumA when LP updated their liquidity last time\\n /// @param sumBInsideLastX128 value of sumB inside range when LP updated their liquidity last time\\n /// @param sumFpInsideLastX128 value of sumFp inside range when LP updated their liquidity last time\\n /// @param liquidity amount of liquidity which was constant for LP in the time duration\\n /// @return amount of vQuote tokens that should be charged if positive\\n function bill(\\n int256 sumAX128,\\n int256 sumFpInsideX128,\\n int256 sumALastX128,\\n int256 sumBInsideLastX128,\\n int256 sumFpInsideLastX128,\\n uint256 liquidity\\n ) internal pure returns (int256) {\\n return\\n (sumFpInsideX128 - extrapolatedSumFpX128(sumALastX128, sumBInsideLastX128, sumFpInsideLastX128, sumAX128))\\n .mulDivRoundingDown(liquidity, FixedPoint128.Q128);\\n }\\n\\n /// @notice Positive bill is charged from Traders, Negative bill is rewarded to Traders\\n /// @param sumAX128 latest value of sumA (to be taken from global state)\\n /// @param sumALastX128 value of sumA when trader updated their netTraderPosition\\n /// @param netTraderPosition oken amount which should be constant for time duration since sumALastX128 was recorded\\n /// @return amount of vQuote tokens that should be charged if positive\\n function bill(\\n int256 sumAX128,\\n int256 sumALastX128,\\n int256 netTraderPosition\\n ) internal pure returns (int256) {\\n return netTraderPosition.mulDiv((sumAX128 - sumALastX128), int256(FixedPoint128.Q128));\\n }\\n}\\n\",\"keccak256\":\"0x7b189aa450af422d069760e170f6631fb48333e0664806aa5cb833a6bc68d339\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/LiquidityPosition.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { SqrtPriceMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/SqrtPriceMath.sol';\\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\nimport { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { PriceMath } from './PriceMath.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\\nimport { FundingPayment } from './FundingPayment.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\n\\n/// @title Liquidity position functions\\nlibrary LiquidityPosition {\\n using FullMath for uint256;\\n using PriceMath for uint160;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n using UniswapV3PoolHelper for IUniswapV3Pool;\\n\\n using LiquidityPosition for LiquidityPosition.Info;\\n using Protocol for Protocol.Info;\\n\\n struct Set {\\n // multiple per pool because it's non-fungible, allows for 4 billion LP positions lifetime\\n uint48[5] active;\\n // concat(tickLow,tickHigh)\\n mapping(uint48 => LiquidityPosition.Info) positions;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n struct Info {\\n //Extra boolean to check if it is limit order and uint to track limit price.\\n IClearingHouseEnums.LimitOrderType limitOrderType;\\n // the tick range of the position;\\n int24 tickLower;\\n int24 tickUpper;\\n // the liquidity of the position\\n uint128 liquidity;\\n int256 vTokenAmountIn;\\n // funding payment checkpoints\\n int256 sumALastX128;\\n int256 sumBInsideLastX128;\\n int256 sumFpInsideLastX128;\\n // fee growth inside\\n uint256 sumFeeInsideLastX128;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n error LP_AlreadyInitialized();\\n error LP_IneligibleLimitOrderRemoval();\\n\\n /// @notice denotes liquidity add/remove\\n /// @param accountId serial number of the account\\n /// @param poolId address of token whose position was taken\\n /// @param tickLower lower tick of the range updated\\n /// @param tickUpper upper tick of the range updated\\n /// @param liquidityDelta change in liquidity value\\n /// @param limitOrderType the type of range position\\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\\n /// @param vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\\n event LiquidityChanged(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n int128 liquidityDelta,\\n IClearingHouseEnums.LimitOrderType limitOrderType,\\n int256 vTokenAmountOut,\\n int256 vQuoteAmountOut,\\n uint160 sqrtPriceX96\\n );\\n\\n /// @param accountId serial number of the account\\n /// @param poolId address of token for which funding was paid\\n /// @param tickLower lower tick of the range for which funding was paid\\n /// @param tickUpper upper tick of the range for which funding was paid\\n /// @param amount amount of funding paid (negative) or received (positive)\\n /// @param sumALastX128 val of sum of the term A in funding payment math, when op took place\\n /// @param sumBInsideLastX128 val of sum of the term B in funding payment math, when op took place\\n /// @param sumFpInsideLastX128 val of sum of the term Fp in funding payment math, when op took place\\n /// @param sumFeeInsideLastX128 val of sum of the term Fee in wrapper, when op took place\\n event LiquidityPositionFundingPaymentRealized(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n int256 amount,\\n int256 sumALastX128,\\n int256 sumBInsideLastX128,\\n int256 sumFpInsideLastX128,\\n uint256 sumFeeInsideLastX128\\n );\\n\\n /// @notice denotes fee payment for a range / token position\\n /// @dev for a token position tickLower = tickUpper = 0\\n /// @param accountId serial number of the account\\n /// @param poolId address of token for which fee was paid\\n /// @param tickLower lower tick of the range for which fee was paid\\n /// @param tickUpper upper tick of the range for which fee was paid\\n /// @param amount amount of fee paid (negative) or received (positive)\\n event LiquidityPositionEarningsRealized(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n int256 amount\\n );\\n\\n /**\\n * Internal methods\\n */\\n\\n /// @notice initializes a new LiquidityPosition.Info struct\\n /// @dev Reverts if the position is already initialized\\n /// @param position storage pointer of the position to initialize\\n /// @param tickLower lower tick of the range\\n /// @param tickUpper upper tick of the range\\n function initialize(\\n LiquidityPosition.Info storage position,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal {\\n if (position.isInitialized()) {\\n revert LP_AlreadyInitialized();\\n }\\n\\n position.tickLower = tickLower;\\n position.tickUpper = tickUpper;\\n }\\n\\n /// @notice changes liquidity for a position, informs pool wrapper and does necessary bookkeeping\\n /// @param position storage ref of the position to update\\n /// @param accountId serial number of the account, used to emit event\\n /// @param poolId id of the pool for which position was updated\\n /// @param liquidityDelta change in liquidity value\\n /// @param balanceAdjustments memory ref to the balance adjustments struct\\n /// @param protocol ref to the protocol state\\n function liquidityChange(\\n LiquidityPosition.Info storage position,\\n uint256 accountId,\\n uint32 poolId,\\n int128 liquidityDelta,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n int256 vTokenPrincipal;\\n int256 vQuotePrincipal;\\n\\n IVPoolWrapper wrapper = protocol.vPoolWrapper(poolId);\\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside;\\n\\n // calls wrapper to mint/burn liquidity\\n if (liquidityDelta > 0) {\\n uint256 vTokenPrincipal_;\\n uint256 vQuotePrincipal_;\\n (vTokenPrincipal_, vQuotePrincipal_, wrapperValuesInside) = wrapper.mint(\\n position.tickLower,\\n position.tickUpper,\\n uint128(liquidityDelta)\\n );\\n vTokenPrincipal = vTokenPrincipal_.toInt256();\\n vQuotePrincipal = vQuotePrincipal_.toInt256();\\n } else {\\n uint256 vTokenPrincipal_;\\n uint256 vQuotePrincipal_;\\n (vTokenPrincipal_, vQuotePrincipal_, wrapperValuesInside) = wrapper.burn(\\n position.tickLower,\\n position.tickUpper,\\n uint128(-liquidityDelta)\\n );\\n vTokenPrincipal = -vTokenPrincipal_.toInt256();\\n vQuotePrincipal = -vQuotePrincipal_.toInt256();\\n }\\n\\n // calculate funding payment and liquidity fees then update checkpoints\\n position.update(accountId, poolId, wrapperValuesInside, balanceAdjustments);\\n\\n // adjust in the token acounts\\n balanceAdjustments.vQuoteIncrease -= vQuotePrincipal;\\n balanceAdjustments.vTokenIncrease -= vTokenPrincipal;\\n\\n // emit the event\\n uint160 sqrtPriceCurrent = protocol.vPool(poolId).sqrtPriceCurrent();\\n emitLiquidityChangeEvent(\\n position,\\n accountId,\\n poolId,\\n liquidityDelta,\\n sqrtPriceCurrent,\\n -vTokenPrincipal,\\n -vQuotePrincipal\\n );\\n\\n // update trader position increase\\n int256 vTokenAmountCurrent;\\n {\\n (vTokenAmountCurrent, ) = position.vTokenAmountsInRange(sqrtPriceCurrent, false);\\n balanceAdjustments.traderPositionIncrease += (vTokenAmountCurrent - position.vTokenAmountIn);\\n }\\n\\n uint128 liquidityNew = position.liquidity;\\n if (liquidityDelta > 0) {\\n liquidityNew += uint128(liquidityDelta);\\n } else if (liquidityDelta < 0) {\\n liquidityNew -= uint128(-liquidityDelta);\\n }\\n\\n if (liquidityNew != 0) {\\n // update state\\n position.liquidity = liquidityNew;\\n position.vTokenAmountIn = vTokenAmountCurrent + vTokenPrincipal;\\n } else {\\n // clear all the state\\n position.liquidity = 0;\\n position.vTokenAmountIn = 0;\\n position.sumALastX128 = 0;\\n position.sumBInsideLastX128 = 0;\\n position.sumFpInsideLastX128 = 0;\\n position.sumFeeInsideLastX128 = 0;\\n }\\n }\\n\\n /// @notice updates the position with latest checkpoints, and realises fees and fp\\n /// @dev fees and funding payment are not immediately adjusted in token balance state,\\n /// balanceAdjustments struct is used to pass the necessary values to caller.\\n /// @param position storage ref of the position to update\\n /// @param accountId serial number of the account, used to emit event\\n /// @param poolId id of the pool for which position was updated\\n /// @param wrapperValuesInside range checkpoint values from the wrapper\\n /// @param balanceAdjustments memory ref to the balance adjustments struct\\n function update(\\n LiquidityPosition.Info storage position,\\n uint256 accountId,\\n uint32 poolId,\\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments\\n ) internal {\\n int256 fundingPayment = position.unrealizedFundingPayment(\\n wrapperValuesInside.sumAX128,\\n wrapperValuesInside.sumFpInsideX128\\n );\\n balanceAdjustments.vQuoteIncrease += fundingPayment;\\n\\n int256 unrealizedLiquidityFee = position.unrealizedFees(wrapperValuesInside.sumFeeInsideX128).toInt256();\\n balanceAdjustments.vQuoteIncrease += unrealizedLiquidityFee;\\n\\n // updating checkpoints\\n position.sumALastX128 = wrapperValuesInside.sumAX128;\\n position.sumBInsideLastX128 = wrapperValuesInside.sumBInsideX128;\\n position.sumFpInsideLastX128 = wrapperValuesInside.sumFpInsideX128;\\n position.sumFeeInsideLastX128 = wrapperValuesInside.sumFeeInsideX128;\\n\\n emit LiquidityPositionFundingPaymentRealized(\\n accountId,\\n poolId,\\n position.tickLower,\\n position.tickUpper,\\n fundingPayment,\\n wrapperValuesInside.sumAX128,\\n wrapperValuesInside.sumBInsideX128,\\n wrapperValuesInside.sumFpInsideX128,\\n wrapperValuesInside.sumFeeInsideX128\\n );\\n\\n emit LiquidityPositionEarningsRealized(\\n accountId,\\n poolId,\\n position.tickLower,\\n position.tickUpper,\\n unrealizedLiquidityFee\\n );\\n }\\n\\n /**\\n * Internal view methods\\n */\\n\\n /// @notice ensures that limit order removal is valid, else reverts\\n /// @param info storage ref of the position to check\\n /// @param currentTick current tick in the pool\\n function checkValidLimitOrderRemoval(LiquidityPosition.Info storage info, int24 currentTick) internal view {\\n if (\\n !((currentTick >= info.tickUpper &&\\n info.limitOrderType == IClearingHouseEnums.LimitOrderType.UPPER_LIMIT) ||\\n (currentTick <= info.tickLower &&\\n info.limitOrderType == IClearingHouseEnums.LimitOrderType.LOWER_LIMIT))\\n ) {\\n revert LP_IneligibleLimitOrderRemoval();\\n }\\n }\\n\\n /// @notice checks if the position is initialized\\n /// @param info storage ref of the position to check\\n /// @return true if the position is initialized\\n function isInitialized(LiquidityPosition.Info storage info) internal view returns (bool) {\\n return info.tickLower != 0 || info.tickUpper != 0;\\n }\\n\\n /// @notice calculates the long side risk for the position\\n /// @param position storage ref of the position to check\\n /// @param valuationSqrtPriceX96 valuation sqrt price in x96\\n /// @return long side risk\\n function longSideRisk(LiquidityPosition.Info storage position, uint160 valuationSqrtPriceX96)\\n internal\\n view\\n returns (uint256)\\n {\\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\\n uint256 longPositionExecutionPriceX128;\\n {\\n uint160 sqrtPriceUpperMinX96 = valuationSqrtPriceX96 <= sqrtPriceUpperX96\\n ? valuationSqrtPriceX96\\n : sqrtPriceUpperX96;\\n uint160 sqrtPriceLowerMinX96 = valuationSqrtPriceX96 <= sqrtPriceLowerX96\\n ? valuationSqrtPriceX96\\n : sqrtPriceLowerX96;\\n longPositionExecutionPriceX128 = uint256(sqrtPriceLowerMinX96).mulDiv(sqrtPriceUpperMinX96, 1 << 64);\\n }\\n\\n uint256 maxNetLongPosition;\\n {\\n uint256 maxLongTokens = SqrtPriceMath.getAmount0Delta(\\n sqrtPriceLowerX96,\\n sqrtPriceUpperX96,\\n position.liquidity,\\n true\\n );\\n //\\n if (position.vTokenAmountIn >= 0) {\\n //maxLongTokens in range should always be >= amount that got added to range, equality occurs when range was added at pCurrent = pHigh\\n assert(maxLongTokens >= uint256(position.vTokenAmountIn));\\n maxNetLongPosition = maxLongTokens - uint256(position.vTokenAmountIn);\\n } else maxNetLongPosition = maxLongTokens + uint256(-1 * position.vTokenAmountIn);\\n }\\n\\n return maxNetLongPosition.mulDiv(longPositionExecutionPriceX128, FixedPoint128.Q128);\\n }\\n\\n /// @notice calculates the market value for the position using a provided price\\n /// @param position storage ref of the position to check\\n /// @param valuationSqrtPriceX96 valuation sqrt price to be used\\n /// @param wrapper address of the pool wrapper\\n /// @return marketValue_ the market value of the position\\n function marketValue(\\n LiquidityPosition.Info storage position,\\n uint160 valuationSqrtPriceX96,\\n IVPoolWrapper wrapper\\n ) internal view returns (int256 marketValue_) {\\n {\\n (int256 vTokenAmount, int256 vQuoteAmount) = position.vTokenAmountsInRange(valuationSqrtPriceX96, false);\\n uint256 priceX128 = valuationSqrtPriceX96.toPriceX128();\\n marketValue_ = vTokenAmount.mulDiv(priceX128, FixedPoint128.Q128) + vQuoteAmount;\\n }\\n // adding fees\\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside = wrapper.getExtrapolatedValuesInside(\\n position.tickLower,\\n position.tickUpper\\n );\\n marketValue_ += position.unrealizedFees(wrapperValuesInside.sumFeeInsideX128).toInt256();\\n marketValue_ += position.unrealizedFundingPayment(\\n wrapperValuesInside.sumAX128,\\n wrapperValuesInside.sumFpInsideX128\\n );\\n }\\n\\n /// @notice calculates the max net position for the position\\n /// @param position storage ref of the position to check\\n /// @return maxNetPosition the max net position of the position\\n function maxNetPosition(LiquidityPosition.Info storage position) internal view returns (uint256) {\\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\\n\\n if (position.vTokenAmountIn >= 0)\\n return\\n SqrtPriceMath.getAmount0Delta(sqrtPriceLowerX96, sqrtPriceUpperX96, position.liquidity, true) -\\n uint256(position.vTokenAmountIn);\\n else\\n return\\n SqrtPriceMath.getAmount0Delta(sqrtPriceLowerX96, sqrtPriceUpperX96, position.liquidity, true) +\\n uint256(-1 * position.vTokenAmountIn);\\n }\\n\\n /// @notice calculates the current net position for the position\\n /// @param position storage ref of the position to check\\n /// @param sqrtPriceCurrent the current sqrt price, used to calculate net position\\n /// @return netTokenPosition the current net position of the position\\n function netPosition(LiquidityPosition.Info storage position, uint160 sqrtPriceCurrent)\\n internal\\n view\\n returns (int256 netTokenPosition)\\n {\\n int256 vTokenAmountCurrent;\\n (vTokenAmountCurrent, ) = position.vTokenAmountsInRange(sqrtPriceCurrent, false);\\n netTokenPosition = (vTokenAmountCurrent - position.vTokenAmountIn);\\n }\\n\\n /// @notice calculates the current virtual token amounts for the position\\n /// @param position storage ref of the position to check\\n /// @param sqrtPriceCurrent the current sqrt price, used to calculate virtual token amounts\\n /// @param roundUp whether to round up the token amounts, purpose to charge user more and give less\\n /// @return vTokenAmount the current vToken amount\\n /// @return vQuoteAmount the current vQuote amount\\n function vTokenAmountsInRange(\\n LiquidityPosition.Info storage position,\\n uint160 sqrtPriceCurrent,\\n bool roundUp\\n ) internal view returns (int256 vTokenAmount, int256 vQuoteAmount) {\\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\\n\\n // If price is outside the range, then consider it at the ends\\n // for calculation of amounts\\n uint160 sqrtPriceMiddleX96 = sqrtPriceCurrent;\\n if (sqrtPriceCurrent < sqrtPriceLowerX96) {\\n sqrtPriceMiddleX96 = sqrtPriceLowerX96;\\n } else if (sqrtPriceCurrent > sqrtPriceUpperX96) {\\n sqrtPriceMiddleX96 = sqrtPriceUpperX96;\\n }\\n\\n vTokenAmount = SqrtPriceMath\\n .getAmount0Delta(sqrtPriceMiddleX96, sqrtPriceUpperX96, position.liquidity, roundUp)\\n .toInt256();\\n vQuoteAmount = SqrtPriceMath\\n .getAmount1Delta(sqrtPriceLowerX96, sqrtPriceMiddleX96, position.liquidity, roundUp)\\n .toInt256();\\n }\\n\\n /// @notice returns vQuoteIncrease due to unrealised funding payment for the liquidity position (+ve means receiving and -ve means giving)\\n /// @param position storage ref of the position to check\\n /// @param sumAX128 the sumA value from the pool wrapper\\n /// @param sumFpInsideX128 the sumFp in the position's range from the pool wrapper\\n /// @return vQuoteIncrease the amount of vQuote that should be added to the account's vQuote balance\\n function unrealizedFundingPayment(\\n LiquidityPosition.Info storage position,\\n int256 sumAX128,\\n int256 sumFpInsideX128\\n ) internal view returns (int256 vQuoteIncrease) {\\n // subtract the bill from the account's vQuote balance\\n vQuoteIncrease = -FundingPayment.bill(\\n sumAX128,\\n sumFpInsideX128,\\n position.sumALastX128,\\n position.sumBInsideLastX128,\\n position.sumFpInsideLastX128,\\n position.liquidity\\n );\\n }\\n\\n /// @notice calculates the unrealised lp fees for the position\\n /// @param position storage ref of the position to check\\n /// @param sumFeeInsideX128 the global sumFee in the position's range from the pool wrapper\\n /// @return vQuoteIncrease the amount of vQuote that should be added to the account's vQuote balance\\n function unrealizedFees(LiquidityPosition.Info storage position, uint256 sumFeeInsideX128)\\n internal\\n view\\n returns (uint256 vQuoteIncrease)\\n {\\n vQuoteIncrease = (sumFeeInsideX128 - position.sumFeeInsideLastX128).mulDiv(\\n position.liquidity,\\n FixedPoint128.Q128\\n );\\n }\\n\\n function emitLiquidityChangeEvent(\\n LiquidityPosition.Info storage position,\\n uint256 accountId,\\n uint32 poolId,\\n int128 liquidityDelta,\\n uint160 sqrtPriceX96,\\n int256 vTokenAmountOut,\\n int256 vQuoteAmountOut\\n ) internal {\\n emit LiquidityChanged(\\n accountId,\\n poolId,\\n position.tickLower,\\n position.tickUpper,\\n liquidityDelta,\\n position.limitOrderType,\\n vTokenAmountOut,\\n vQuoteAmountOut,\\n sqrtPriceX96\\n );\\n }\\n}\\n\",\"keccak256\":\"0xdd835fed27adf6c4168843bbfa7074d29fd5b0cc25cee891b20bf353b18e985a\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/LiquidityPositionSet.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { LiquidityPosition } from './LiquidityPosition.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { Uint48Lib } from './Uint48.sol';\\nimport { Uint48L5ArrayLib } from './Uint48L5Array.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\n\\n/// @title Liquidity position set functions\\nlibrary LiquidityPositionSet {\\n using LiquidityPosition for LiquidityPosition.Info;\\n using LiquidityPositionSet for LiquidityPosition.Set;\\n using Protocol for Protocol.Info;\\n using Uint48Lib for int24;\\n using Uint48Lib for uint48;\\n using Uint48L5ArrayLib for uint48[5];\\n\\n error LPS_IllegalTicks(int24 tickLower, int24 tickUpper);\\n error LPS_DeactivationFailed(int24 tickLower, int24 tickUpper, uint256 liquidity);\\n error LPS_InactiveRange();\\n\\n /// @notice denotes token position change due to liquidity add/remove\\n /// @param accountId serial number of the account\\n /// @param poolId address of token whose position was taken\\n /// @param tickLower lower tick of the range updated\\n /// @param tickUpper upper tick of the range updated\\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\\n event TokenPositionChangedDueToLiquidityChanged(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n int256 vTokenAmountOut\\n );\\n\\n /**\\n * Internal methods\\n */\\n\\n /// @notice activates a position by initializing it and adding it to the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param tickLower lower tick of the range to be activated\\n /// @param tickUpper upper tick of the range to be activated\\n /// @return position storage ref of the activated position\\n function activate(\\n LiquidityPosition.Set storage set,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal returns (LiquidityPosition.Info storage position) {\\n if (tickLower > tickUpper) {\\n revert LPS_IllegalTicks(tickLower, tickUpper);\\n }\\n\\n uint48 positionId;\\n set.active.include(positionId = tickLower.concat(tickUpper));\\n position = set.positions[positionId];\\n\\n if (!position.isInitialized()) {\\n position.initialize(tickLower, tickUpper);\\n }\\n }\\n\\n /// @notice deactivates a position by removing it from the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param position storage ref to the position to be deactivated\\n function deactivate(LiquidityPosition.Set storage set, LiquidityPosition.Info storage position) internal {\\n if (position.liquidity != 0) {\\n revert LPS_DeactivationFailed(position.tickLower, position.tickUpper, position.liquidity);\\n }\\n\\n set.active.exclude(position.tickLower.concat(position.tickUpper));\\n }\\n\\n /// @notice changes liquidity of a position in the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param liquidityChangeParams parameters of the liquidity change\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function liquidityChange(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n LiquidityPosition.Info storage position = set.activate(\\n liquidityChangeParams.tickLower,\\n liquidityChangeParams.tickUpper\\n );\\n\\n position.limitOrderType = liquidityChangeParams.limitOrderType;\\n\\n set.liquidityChange(\\n accountId,\\n poolId,\\n position,\\n liquidityChangeParams.liquidityDelta,\\n balanceAdjustments,\\n protocol\\n );\\n }\\n\\n /// @notice changes liquidity of a position in the set\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param position storage ref to the position to be changed\\n /// @param liquidityDelta amount of liquidity to be added or removed\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function liquidityChange(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n LiquidityPosition.Info storage position,\\n int128 liquidityDelta,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n position.liquidityChange(accountId, poolId, liquidityDelta, balanceAdjustments, protocol);\\n\\n emit TokenPositionChangedDueToLiquidityChanged(\\n accountId,\\n poolId,\\n position.tickLower,\\n position.tickUpper,\\n balanceAdjustments.vTokenIncrease\\n );\\n\\n if (position.liquidity == 0) {\\n set.deactivate(position);\\n }\\n }\\n\\n /// @notice removes liquidity from a position in the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param position storage ref to the position to be closed\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function closeLiquidityPosition(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n LiquidityPosition.Info storage position,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n set.liquidityChange(accountId, poolId, position, -int128(position.liquidity), balanceAdjustments, protocol);\\n }\\n\\n /// @notice removes liquidity from a position in the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param currentTick current tick of the pool\\n /// @param tickLower lower tick of the range to be closed\\n /// @param tickUpper upper tick of the range to be closed\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function removeLimitOrder(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n int24 currentTick,\\n int24 tickLower,\\n int24 tickUpper,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n LiquidityPosition.Info storage position = set.getLiquidityPosition(tickLower, tickUpper);\\n position.checkValidLimitOrderRemoval(currentTick);\\n set.closeLiquidityPosition(accountId, poolId, position, balanceAdjustments, protocol);\\n }\\n\\n /// @notice removes liquidity from all the positions in the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function closeAllLiquidityPositions(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n LiquidityPosition.Info storage position;\\n\\n while (set.active[0] != 0) {\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustmentsCurrent;\\n\\n position = set.positions[set.active[0]];\\n\\n set.closeLiquidityPosition(accountId, poolId, position, balanceAdjustmentsCurrent, protocol);\\n\\n balanceAdjustments.vQuoteIncrease += balanceAdjustmentsCurrent.vQuoteIncrease;\\n balanceAdjustments.vTokenIncrease += balanceAdjustmentsCurrent.vTokenIncrease;\\n balanceAdjustments.traderPositionIncrease += balanceAdjustmentsCurrent.traderPositionIncrease;\\n }\\n }\\n\\n /**\\n * Internal view methods\\n */\\n\\n /// @notice gets the liquidity position of a tick range\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param tickLower lower tick of the range to be closed\\n /// @param tickUpper upper tick of the range to be closed\\n /// @return position liquidity position of the tick range\\n function getLiquidityPosition(\\n LiquidityPosition.Set storage set,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal view returns (LiquidityPosition.Info storage position) {\\n if (tickLower > tickUpper) {\\n revert LPS_IllegalTicks(tickLower, tickUpper);\\n }\\n\\n uint48 positionId = Uint48Lib.concat(tickLower, tickUpper);\\n position = set.positions[positionId];\\n\\n if (!position.isInitialized()) revert LPS_InactiveRange();\\n return position;\\n }\\n\\n /// @notice gets information about all the liquidity position\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @return liquidityPositions Information about all the liquidity position for the pool\\n function getInfo(LiquidityPosition.Set storage set)\\n internal\\n view\\n returns (IClearingHouseStructures.LiquidityPositionView[] memory liquidityPositions)\\n {\\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\\n liquidityPositions = new IClearingHouseStructures.LiquidityPositionView[](numberOfTokenPositions);\\n\\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\\n liquidityPositions[i].limitOrderType = set.positions[set.active[i]].limitOrderType;\\n liquidityPositions[i].tickLower = set.positions[set.active[i]].tickLower;\\n liquidityPositions[i].tickUpper = set.positions[set.active[i]].tickUpper;\\n liquidityPositions[i].liquidity = set.positions[set.active[i]].liquidity;\\n liquidityPositions[i].vTokenAmountIn = set.positions[set.active[i]].vTokenAmountIn;\\n liquidityPositions[i].sumALastX128 = set.positions[set.active[i]].sumALastX128;\\n liquidityPositions[i].sumBInsideLastX128 = set.positions[set.active[i]].sumBInsideLastX128;\\n liquidityPositions[i].sumFpInsideLastX128 = set.positions[set.active[i]].sumFpInsideLastX128;\\n liquidityPositions[i].sumFeeInsideLastX128 = set.positions[set.active[i]].sumFeeInsideLastX128;\\n }\\n }\\n\\n /// @notice gets the net position due to all the liquidity positions\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param sqrtPriceCurrent current sqrt price of the pool\\n /// @return netPosition due to all the liquidity positions\\n function getNetPosition(LiquidityPosition.Set storage set, uint160 sqrtPriceCurrent)\\n internal\\n view\\n returns (int256 netPosition)\\n {\\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\\n\\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\\n netPosition += set.positions[set.active[i]].netPosition(sqrtPriceCurrent);\\n }\\n }\\n\\n /// @notice checks whether the liquidity position set is empty\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @return true if the liquidity position set is empty\\n function isEmpty(LiquidityPosition.Set storage set) internal view returns (bool) {\\n return set.active.isEmpty();\\n }\\n\\n /// @notice checks whether for given ticks, a liquidity position is active\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param tickLower lower tick of the range\\n /// @param tickUpper upper tick of the range\\n /// @return true if the liquidity position is active\\n function isPositionActive(\\n LiquidityPosition.Set storage set,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal view returns (bool) {\\n return set.active.exists(tickLower.concat(tickUpper));\\n }\\n\\n /// @notice gets the total long side risk for all the active liquidity positions\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param valuationPriceX96 price used to value the vToken asset\\n /// @return risk the net long side risk for all the active liquidity positions\\n function longSideRisk(LiquidityPosition.Set storage set, uint160 valuationPriceX96)\\n internal\\n view\\n returns (uint256 risk)\\n {\\n for (uint256 i = 0; i < set.active.length; i++) {\\n uint48 id = set.active[i];\\n if (id == 0) break;\\n risk += set.positions[id].longSideRisk(valuationPriceX96);\\n }\\n }\\n\\n /// @notice gets the total market value of all the active liquidity positions\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param sqrtPriceCurrent price used to value the vToken asset\\n /// @param poolId the id of the pool\\n /// @param protocol ref to the state of the protocol\\n /// @return marketValue_ the total market value of all the active liquidity positions\\n function marketValue(\\n LiquidityPosition.Set storage set,\\n uint160 sqrtPriceCurrent,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 marketValue_) {\\n marketValue_ = set.marketValue(sqrtPriceCurrent, protocol.vPoolWrapper(poolId));\\n }\\n\\n /// @notice Get the total market value of all active liquidity positions in the set.\\n /// @param set: Collection of active liquidity positions\\n /// @param sqrtPriceCurrent: Current price of the virtual asset\\n /// @param wrapper: address of the wrapper contract, passed once to avoid multiple sloads for wrapper\\n function marketValue(\\n LiquidityPosition.Set storage set,\\n uint160 sqrtPriceCurrent,\\n IVPoolWrapper wrapper\\n ) internal view returns (int256 marketValue_) {\\n for (uint256 i = 0; i < set.active.length; i++) {\\n uint48 id = set.active[i];\\n if (id == 0) break;\\n marketValue_ += set.positions[id].marketValue(sqrtPriceCurrent, wrapper);\\n }\\n }\\n\\n /// @notice gets the max net position possible due to all the liquidity positions\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @return risk the max net position possible due to all the liquidity positions\\n function maxNetPosition(LiquidityPosition.Set storage set) internal view returns (uint256 risk) {\\n for (uint256 i = 0; i < set.active.length; i++) {\\n uint48 id = set.active[i];\\n if (id == 0) break;\\n risk += set.positions[id].maxNetPosition();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x20552c4941db1f89a751daa063774d5daa0a8dbad241e43bf1abf91f6e653d5c\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/PriceMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';\\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\\n\\nimport { Bisection } from './Bisection.sol';\\n\\n/// @title Price math functions\\nlibrary PriceMath {\\n using FullMath for uint256;\\n\\n error IllegalSqrtPrice(uint160 sqrtPriceX96);\\n\\n /// @notice Computes the square of a sqrtPriceX96 value\\n /// @param sqrtPriceX96: the square root of the input price in Q96 format\\n /// @return priceX128 : input price in Q128 format\\n function toPriceX128(uint160 sqrtPriceX96) internal pure returns (uint256 priceX128) {\\n if (sqrtPriceX96 < TickMath.MIN_SQRT_RATIO || sqrtPriceX96 >= TickMath.MAX_SQRT_RATIO) {\\n revert IllegalSqrtPrice(sqrtPriceX96);\\n }\\n\\n priceX128 = _toPriceX128(sqrtPriceX96);\\n }\\n\\n /// @notice computes the square of a sqrtPriceX96 value\\n /// @param sqrtPriceX96: input price in Q128 format\\n function _toPriceX128(uint160 sqrtPriceX96) private pure returns (uint256 priceX128) {\\n priceX128 = uint256(sqrtPriceX96).mulDiv(sqrtPriceX96, 1 << 64);\\n }\\n\\n /// @notice computes the square root of a priceX128 value\\n /// @param priceX128: input price in Q128 format\\n /// @return sqrtPriceX96 : the square root of the input price in Q96 format\\n function toSqrtPriceX96(uint256 priceX128) internal pure returns (uint160 sqrtPriceX96) {\\n // Uses bisection method to find solution to the equation toPriceX128(x) = priceX128\\n sqrtPriceX96 = Bisection.findSolution(\\n _toPriceX128,\\n priceX128,\\n /// @dev sqrtPriceX96 is always bounded by MIN_SQRT_RATIO and MAX_SQRT_RATIO.\\n /// If solution falls outside of these bounds, findSolution method reverts\\n TickMath.MIN_SQRT_RATIO,\\n TickMath.MAX_SQRT_RATIO - 1\\n );\\n }\\n}\\n\",\"keccak256\":\"0x88bb3e3cb05a8474c5e69c26e2c29bf382a82a4d460f79674ae407114463c3b7\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/Protocol.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { Math } from '@openzeppelin/contracts/utils/math/Math.sol';\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IVQuote } from '../interfaces/IVQuote.sol';\\nimport { IVToken } from '../interfaces/IVToken.sol';\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\n\\nimport { PriceMath } from './PriceMath.sol';\\nimport { SafeCast } from './SafeCast.sol';\\nimport { SignedMath } from './SignedMath.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\\nimport { Block } from './Block.sol';\\nimport { SafeCast } from './SafeCast.sol';\\n\\n/// @title Protocol storage functions\\n/// @dev This is used as main storage interface containing protocol info\\nlibrary Protocol {\\n using FullMath for uint256;\\n using PriceMath for uint160;\\n using PriceMath for uint256;\\n using SignedMath for int256;\\n using SignedFullMath for int256;\\n using SafeCast for uint256;\\n using UniswapV3PoolHelper for IUniswapV3Pool;\\n using SafeCast for uint256;\\n\\n using Protocol for Protocol.Info;\\n\\n struct PriceCache {\\n uint32 updateBlockNumber;\\n uint224 virtualPriceX128;\\n uint224 realPriceX128;\\n bool isDeviationBreached;\\n }\\n struct Info {\\n // poolId => PoolInfo\\n mapping(uint32 => IClearingHouseStructures.Pool) pools;\\n // collateralId => CollateralInfo\\n mapping(uint32 => IClearingHouseStructures.Collateral) collaterals;\\n // iterable and increasing list of pools (used for admin functions)\\n uint32[] poolIds;\\n // settlement token (default collateral)\\n IERC20 settlementToken;\\n // virtual quote token (sort of fake USDC), is always token1 in uniswap pools\\n IVQuote vQuote;\\n // accounting settings\\n IClearingHouseStructures.LiquidationParams liquidationParams;\\n uint256 minRequiredMargin;\\n uint256 removeLimitOrderFee;\\n uint256 minimumOrderNotional;\\n // price cache\\n mapping(uint32 => PriceCache) priceCache;\\n // reserved for adding slots in future\\n uint256[100] _emptySlots;\\n }\\n\\n function updatePoolPriceCache(Protocol.Info storage protocol, uint32 poolId) internal {\\n uint32 blockNumber = Block.number();\\n\\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\\n if (poolPriceCache.updateBlockNumber == blockNumber) {\\n return;\\n }\\n\\n uint256 realPriceX128 = protocol.getRealTwapPriceX128(poolId);\\n uint256 virtualPriceX128 = protocol.getVirtualTwapPriceX128(poolId);\\n\\n // In case the price is breaching the Q224 limit, we do not cache it\\n uint256 Q224 = 1 << 224;\\n if (realPriceX128 >= Q224 || virtualPriceX128 >= Q224) {\\n return;\\n }\\n\\n uint16 maxDeviationBps = protocol.pools[poolId].settings.maxVirtualPriceDeviationRatioBps;\\n if (\\n // if virtual price is too off from real price then screw that, we'll just use real price\\n (int256(realPriceX128) - int256(virtualPriceX128)).absUint() > realPriceX128.mulDiv(maxDeviationBps, 1e4)\\n ) {\\n poolPriceCache.isDeviationBreached = true;\\n } else {\\n poolPriceCache.isDeviationBreached = false;\\n }\\n poolPriceCache.realPriceX128 = realPriceX128.toUint224();\\n poolPriceCache.virtualPriceX128 = virtualPriceX128.toUint224();\\n poolPriceCache.updateBlockNumber = blockNumber;\\n }\\n\\n /// @notice gets the uniswap v3 pool address for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return UniswapV3Pool contract object\\n function vPool(Protocol.Info storage protocol, uint32 poolId) internal view returns (IUniswapV3Pool) {\\n return protocol.pools[poolId].vPool;\\n }\\n\\n /// @notice gets the wrapper address for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return VPoolWrapper contract object\\n function vPoolWrapper(Protocol.Info storage protocol, uint32 poolId) internal view returns (IVPoolWrapper) {\\n return protocol.pools[poolId].vPoolWrapper;\\n }\\n\\n /// @notice gets the virtual twap sqrt price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return sqrtPriceX96 virtual twap sqrt price\\n function getVirtualTwapSqrtPriceX96(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint160 sqrtPriceX96)\\n {\\n IClearingHouseStructures.Pool storage pool = protocol.pools[poolId];\\n return pool.vPool.twapSqrtPrice(pool.settings.twapDuration);\\n }\\n\\n /// @notice gets the virtual current sqrt price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return sqrtPriceX96 virtual current sqrt price\\n function getVirtualCurrentSqrtPriceX96(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint160 sqrtPriceX96)\\n {\\n return protocol.pools[poolId].vPool.sqrtPriceCurrent();\\n }\\n\\n /// @notice gets the virtual current tick for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return tick virtual current tick\\n function getVirtualCurrentTick(Protocol.Info storage protocol, uint32 poolId) internal view returns (int24 tick) {\\n return protocol.pools[poolId].vPool.tickCurrent();\\n }\\n\\n /// @notice gets the virtual twap price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return priceX128 virtual twap price\\n function getVirtualTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n return protocol.getVirtualTwapSqrtPriceX96(poolId).toPriceX128();\\n }\\n\\n /// @notice gets the virtual current price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return priceX128 virtual current price\\n function getVirtualCurrentPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n return protocol.getVirtualCurrentSqrtPriceX96(poolId).toPriceX128();\\n }\\n\\n /// @notice gets the real twap price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return priceX128 virtual twap price\\n function getRealTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n IClearingHouseStructures.Pool storage pool = protocol.pools[poolId];\\n return pool.settings.oracle.getTwapPriceX128(pool.settings.twapDuration);\\n }\\n\\n /// @notice gets the twap prices with deviation check for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return realPriceX128 the real price\\n /// @return virtualPriceX128 the virtual price if under deviation else real price\\n function getTwapPricesWithDeviationCheck(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 realPriceX128, uint256 virtualPriceX128)\\n {\\n realPriceX128 = protocol.getRealTwapPriceX128(poolId);\\n virtualPriceX128 = protocol.getVirtualTwapPriceX128(poolId);\\n\\n uint16 maxDeviationBps = protocol.pools[poolId].settings.maxVirtualPriceDeviationRatioBps;\\n uint256 priceDeltaX128 = realPriceX128 > virtualPriceX128\\n ? realPriceX128 - virtualPriceX128\\n : virtualPriceX128 - realPriceX128;\\n if (priceDeltaX128 > realPriceX128.mulDiv(maxDeviationBps, 1e4)) {\\n // if virtual price is too off from real price then screw that, we'll just use real price\\n virtualPriceX128 = realPriceX128;\\n }\\n return (realPriceX128, virtualPriceX128);\\n }\\n\\n function getCachedVirtualTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n uint32 blockNumber = Block.number();\\n\\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\\n if (poolPriceCache.updateBlockNumber == blockNumber) {\\n return poolPriceCache.virtualPriceX128;\\n } else {\\n return protocol.getVirtualTwapPriceX128(poolId);\\n }\\n }\\n\\n function getCachedTwapPricesWithDeviationCheck(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 realPriceX128, uint256 virtualPriceX128)\\n {\\n uint32 blockNumber = Block.number();\\n\\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\\n if (poolPriceCache.updateBlockNumber == blockNumber) {\\n if (poolPriceCache.isDeviationBreached) {\\n return (poolPriceCache.realPriceX128, poolPriceCache.realPriceX128);\\n } else {\\n return (poolPriceCache.realPriceX128, poolPriceCache.virtualPriceX128);\\n }\\n } else {\\n return protocol.getTwapPricesWithDeviationCheck(poolId);\\n }\\n }\\n\\n function getCachedRealTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n uint32 blockNumber = Block.number();\\n\\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\\n if (poolPriceCache.updateBlockNumber == blockNumber) {\\n return poolPriceCache.realPriceX128;\\n } else {\\n return protocol.getRealTwapPriceX128(poolId);\\n }\\n }\\n\\n /// @notice gets the margin ratio for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @param isInitialMargin whether to use initial margin or maintainance margin\\n /// @return margin rato in bps\\n function getMarginRatioBps(\\n Protocol.Info storage protocol,\\n uint32 poolId,\\n bool isInitialMargin\\n ) internal view returns (uint16) {\\n if (isInitialMargin) {\\n return protocol.pools[poolId].settings.initialMarginRatioBps;\\n } else {\\n return protocol.pools[poolId].settings.maintainanceMarginRatioBps;\\n }\\n }\\n\\n /// @notice checks if the pool is cross margined\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return bool whether the pool is cross margined\\n function isPoolCrossMargined(Protocol.Info storage protocol, uint32 poolId) internal view returns (bool) {\\n return protocol.pools[poolId].settings.isCrossMargined;\\n }\\n\\n /// @notice Gives notional value of the given vToken and vQuote amounts\\n /// @param protocol platform constants\\n /// @param poolId id of the rage trade pool\\n /// @param vTokenAmount amount of tokens\\n /// @param vQuoteAmount amount of base\\n /// @return notionalValue for the given token and vQuote amounts\\n function getNotionalValue(\\n Protocol.Info storage protocol,\\n uint32 poolId,\\n int256 vTokenAmount,\\n int256 vQuoteAmount\\n ) internal view returns (uint256 notionalValue) {\\n return\\n vTokenAmount.absUint().mulDiv(protocol.getCachedVirtualTwapPriceX128(poolId), FixedPoint128.Q128) +\\n vQuoteAmount.absUint();\\n }\\n\\n /// @notice Gives notional value of the given token amount\\n /// @param protocol platform constants\\n /// @param poolId id of the rage trade pool\\n /// @param vTokenAmount amount of tokens\\n /// @return notionalValue for the given token and vQuote amounts\\n function getNotionalValue(\\n Protocol.Info storage protocol,\\n uint32 poolId,\\n int256 vTokenAmount\\n ) internal view returns (uint256 notionalValue) {\\n return protocol.getNotionalValue(poolId, vTokenAmount, 0);\\n }\\n}\\n\",\"keccak256\":\"0x274ddcd8f199b7505377bdeda516d4de0db10dd03222bcdf7eb8fb94ca4092a0\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\n/// @title Safe cast functions\\nlibrary SafeCast {\\n error SafeCast_Int128Overflow(uint128 value);\\n\\n function toInt128(uint128 y) internal pure returns (int128 z) {\\n unchecked {\\n if (y >= 2**127) revert SafeCast_Int128Overflow(y);\\n z = int128(y);\\n }\\n }\\n\\n error SafeCast_Int256Overflow(uint256 value);\\n\\n function toInt256(uint256 y) internal pure returns (int256 z) {\\n unchecked {\\n if (y >= 2**255) revert SafeCast_Int256Overflow(y);\\n z = int256(y);\\n }\\n }\\n\\n error SafeCast_UInt224Overflow(uint256 value);\\n\\n function toUint224(uint256 y) internal pure returns (uint224 z) {\\n if (y > 2**224) revert SafeCast_UInt224Overflow(y);\\n z = uint224(y);\\n }\\n}\\n\",\"keccak256\":\"0xdc96976b23016f06a21a9db7e01c509dff6c9f6ebbdca3dba0043cdfae3405eb\",\"license\":\"MIT\"},\"contracts/libraries/SignedFullMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\n\\nimport { SignedMath } from './SignedMath.sol';\\n\\n/// @title Signed full math functions\\nlibrary SignedFullMath {\\n using SafeCast for uint256;\\n using SignedMath for int256;\\n\\n /// @notice uses full math on signed int and two unsigned ints\\n /// @param a: signed int\\n /// @param b: unsigned int to be multiplied by\\n /// @param denominator: unsigned int to be divided by\\n /// @return result of a * b / denominator\\n function mulDiv(\\n int256 a,\\n uint256 b,\\n uint256 denominator\\n ) internal pure returns (int256 result) {\\n result = FullMath.mulDiv(a < 0 ? uint256(-1 * a) : uint256(a), b, denominator).toInt256();\\n if (a < 0) {\\n result = -result;\\n }\\n }\\n\\n /// @notice uses full math on three signed ints\\n /// @param a: signed int\\n /// @param b: signed int to be multiplied by\\n /// @param denominator: signed int to be divided by\\n /// @return result of a * b / denominator\\n function mulDiv(\\n int256 a,\\n int256 b,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n bool resultPositive = true;\\n uint256 _a;\\n uint256 _b;\\n uint256 _denominator;\\n\\n (_a, resultPositive) = a.extractSign(resultPositive);\\n (_b, resultPositive) = b.extractSign(resultPositive);\\n (_denominator, resultPositive) = denominator.extractSign(resultPositive);\\n\\n result = FullMath.mulDiv(_a, _b, _denominator).toInt256();\\n if (!resultPositive) {\\n result = -result;\\n }\\n }\\n\\n /// @notice rounds down towards negative infinity\\n /// @dev in Solidity -3/2 is -1. But this method result is -2\\n /// @param a: signed int\\n /// @param b: unsigned int to be multiplied by\\n /// @param denominator: unsigned int to be divided by\\n /// @return result of a * b / denominator rounded towards negative infinity\\n function mulDivRoundingDown(\\n int256 a,\\n uint256 b,\\n uint256 denominator\\n ) internal pure returns (int256 result) {\\n result = mulDiv(a, b, denominator);\\n if (result < 0 && _hasRemainder(a.absUint(), b, denominator)) {\\n result += -1;\\n }\\n }\\n\\n /// @notice rounds down towards negative infinity\\n /// @dev in Solidity -3/2 is -1. But this method result is -2\\n /// @param a: signed int\\n /// @param b: signed int to be multiplied by\\n /// @param denominator: signed int to be divided by\\n /// @return result of a * b / denominator rounded towards negative infinity\\n function mulDivRoundingDown(\\n int256 a,\\n int256 b,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n result = mulDiv(a, b, denominator);\\n if (result < 0 && _hasRemainder(a.absUint(), b.absUint(), denominator.absUint())) {\\n result += -1;\\n }\\n }\\n\\n /// @notice checks if full multiplication of a & b would have a remainder if divided by denominator\\n /// @param a: multiplicand\\n /// @param b: multiplier\\n /// @param denominator: divisor\\n /// @return hasRemainder true if there is a remainder, false otherwise\\n function _hasRemainder(\\n uint256 a,\\n uint256 b,\\n uint256 denominator\\n ) private pure returns (bool hasRemainder) {\\n assembly {\\n let remainder := mulmod(a, b, denominator)\\n if gt(remainder, 0) {\\n hasRemainder := 1\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6b5879e3d8f8c0ef8583034f007af7f5d566bc512ea15ab0a26eeeed1092ede3\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nint256 constant ONE = 1;\\n\\n/// @title Signed math functions\\nlibrary SignedMath {\\n /// @notice gives the absolute value of a signed int\\n /// @param value signed int\\n /// @return absolute value of signed int\\n function abs(int256 value) internal pure returns (int256) {\\n return value > 0 ? value : -value;\\n }\\n\\n /// @notice gives the absolute value of a signed int\\n /// @param value signed int\\n /// @return absolute value of signed int as unsigned int\\n function absUint(int256 value) internal pure returns (uint256) {\\n return uint256(abs(value));\\n }\\n\\n /// @notice gives the sign of a signed int\\n /// @param value signed int\\n /// @return -1 if negative, 1 if non-negative\\n function sign(int256 value) internal pure returns (int256) {\\n return value >= 0 ? ONE : -ONE;\\n }\\n\\n /// @notice converts a signed integer into an unsigned integer and inverts positive bool if negative\\n /// @param a signed int\\n /// @param positive initial value of positive bool\\n /// @return _a absolute value of int provided\\n /// @return bool xor of the positive boolean and sign of the provided int\\n function extractSign(int256 a, bool positive) internal pure returns (uint256 _a, bool) {\\n if (a < 0) {\\n positive = !positive;\\n _a = uint256(-a);\\n } else {\\n _a = uint256(a);\\n }\\n return (_a, positive);\\n }\\n\\n /// @notice extracts the sign of a signed int\\n /// @param a signed int\\n /// @return _a unsigned int\\n /// @return bool sign of the provided int\\n function extractSign(int256 a) internal pure returns (uint256 _a, bool) {\\n return extractSign(a, true);\\n }\\n\\n /// @notice returns the max of two int256 numbers\\n /// @param a first number\\n /// @param b second number\\n /// @return c = max of a and b\\n function max(int256 a, int256 b) internal pure returns (int256 c) {\\n if (a > b) c = a;\\n else c = b;\\n }\\n}\\n\",\"keccak256\":\"0xe8218625e89406a3695c78794ec72eea5c3a4db9ef677ce6c36037d5f0431258\",\"license\":\"MIT\"},\"contracts/libraries/Uint32L8Array.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\n/// @title Uint32 length 8 array functions\\n/// @dev Fits in one storage slot\\nlibrary Uint32L8ArrayLib {\\n using Uint32L8ArrayLib for uint32[8];\\n\\n uint8 constant LENGTH = 8;\\n\\n error U32L8_IllegalElement(uint32 element);\\n error U32L8_NoSpaceLeftToInsert(uint32 element);\\n\\n /// @notice Inserts an element in the array\\n /// @dev Replaces a zero value in the array with element\\n /// @param array Array to modify\\n /// @param element Element to insert\\n function include(uint32[8] storage array, uint32 element) internal {\\n if (element == 0) {\\n revert U32L8_IllegalElement(0);\\n }\\n\\n uint256 emptyIndex = LENGTH; // LENGTH is an invalid index\\n for (uint256 i; i < LENGTH; i++) {\\n if (array[i] == element) {\\n // if element already exists in the array, do nothing\\n return;\\n }\\n // if we found an empty slot, remember it\\n if (array[i] == uint32(0)) {\\n emptyIndex = i;\\n break;\\n }\\n }\\n\\n // if empty index is still LENGTH, there is no space left to insert\\n if (emptyIndex == LENGTH) {\\n revert U32L8_NoSpaceLeftToInsert(element);\\n }\\n\\n array[emptyIndex] = element;\\n }\\n\\n /// @notice Excludes the element from the array\\n /// @dev If element exists, it swaps with last element and makes last element zero\\n /// @param array Array to modify\\n /// @param element Element to remove\\n function exclude(uint32[8] storage array, uint32 element) internal {\\n if (element == 0) {\\n revert U32L8_IllegalElement(0);\\n }\\n\\n uint256 elementIndex = LENGTH; // LENGTH is an invalid index\\n uint256 i;\\n\\n for (; i < LENGTH; i++) {\\n if (array[i] == element) {\\n // element index in the array\\n elementIndex = i;\\n }\\n if (array[i] == 0) {\\n // last non-zero element\\n i = i > 0 ? i - 1 : 0;\\n break;\\n }\\n }\\n\\n // if array is full, i == LENGTH\\n // hence swapping with element at last index\\n i = i == LENGTH ? LENGTH - 1 : i;\\n\\n if (elementIndex != LENGTH) {\\n if (i == elementIndex) {\\n // if element is last element, simply make it zero\\n array[elementIndex] = 0;\\n } else {\\n // move last to element's place and empty lastIndex slot\\n (array[elementIndex], array[i]) = (array[i], 0);\\n }\\n }\\n }\\n\\n /// @notice Returns the index of the element in the array\\n /// @param array Array to perform search on\\n /// @param element Element to search\\n /// @return index if exists or LENGTH otherwise\\n function indexOf(uint32[8] storage array, uint32 element) internal view returns (uint8) {\\n for (uint8 i; i < LENGTH; i++) {\\n if (array[i] == element) {\\n return i;\\n }\\n }\\n return LENGTH; // LENGTH is an invalid index\\n }\\n\\n /// @notice Checks whether the element exists in the array\\n /// @param array Array to perform search on\\n /// @param element Element to search\\n /// @return True if element is found, false otherwise\\n function exists(uint32[8] storage array, uint32 element) internal view returns (bool) {\\n return array.indexOf(element) != LENGTH; // LENGTH is an invalid index\\n }\\n\\n /// @notice Returns length of array (number of non-zero elements)\\n /// @param array Array to perform search on\\n /// @return Length of array\\n function numberOfNonZeroElements(uint32[8] storage array) internal view returns (uint256) {\\n for (uint8 i; i < LENGTH; i++) {\\n if (array[i] == 0) {\\n return i;\\n }\\n }\\n return LENGTH;\\n }\\n\\n /// @notice Checks whether the array is empty or not\\n /// @param array Array to perform search on\\n /// @return True if the set does not have any token position active\\n function isEmpty(uint32[8] storage array) internal view returns (bool) {\\n return array[0] == 0;\\n }\\n}\\n\",\"keccak256\":\"0x19d249c0ea7212d517f47603e41606eb0d17f60b64b8d6750f36f578e9d4ea88\",\"license\":\"MIT\"},\"contracts/libraries/Uint48.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\n/// @title Uint48 concating functions\\nlibrary Uint48Lib {\\n /// @notice Packs two int24 values into uint48\\n /// @dev Used for concating two ticks into 48 bits value\\n /// @param val1 First 24 bits value\\n /// @param val2 Second 24 bits value\\n /// @return concatenated value\\n function concat(int24 val1, int24 val2) internal pure returns (uint48 concatenated) {\\n assembly {\\n concatenated := add(shl(24, val1), and(val2, 0x000000ffffff))\\n }\\n }\\n\\n /// @notice Unpacks uint48 into two int24 values\\n /// @dev Used for unpacking 48 bits value into two 24 bits values\\n /// @param concatenated 48 bits value\\n /// @return val1 First 24 bits value\\n /// @return val2 Second 24 bits value\\n function unconcat(uint48 concatenated) internal pure returns (int24 val1, int24 val2) {\\n assembly {\\n val2 := concatenated\\n val1 := shr(24, concatenated)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x68c948293e2c5ee54c07b65af3a3713c5ddc9d2ae68dbc4ada6757773046f475\",\"license\":\"MIT\"},\"contracts/libraries/Uint48L5Array.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\n/// @title Uint48 length 5 array functions\\n/// @dev Fits in one storage slot\\nlibrary Uint48L5ArrayLib {\\n using Uint48L5ArrayLib for uint48[5];\\n\\n uint8 constant LENGTH = 5;\\n\\n error U48L5_IllegalElement(uint48 element);\\n error U48L5_NoSpaceLeftToInsert(uint48 element);\\n\\n /// @notice Inserts an element in the array\\n /// @dev Replaces a zero value in the array with element\\n /// @param array Array to modify\\n /// @param element Element to insert\\n function include(uint48[5] storage array, uint48 element) internal {\\n if (element == 0) {\\n revert U48L5_IllegalElement(0);\\n }\\n\\n uint256 emptyIndex = LENGTH; // LENGTH is an invalid index\\n for (uint256 i; i < LENGTH; i++) {\\n if (array[i] == element) {\\n // if element already exists in the array, do nothing\\n return;\\n }\\n // if we found an empty slot, remember it\\n if (array[i] == uint48(0)) {\\n emptyIndex = i;\\n break;\\n }\\n }\\n\\n // if empty index is still LENGTH, there is no space left to insert\\n if (emptyIndex == LENGTH) {\\n revert U48L5_NoSpaceLeftToInsert(element);\\n }\\n\\n array[emptyIndex] = element;\\n }\\n\\n /// @notice Excludes the element from the array\\n /// @dev If element exists, it swaps with last element and makes last element zero\\n /// @param array Array to modify\\n /// @param element Element to remove\\n function exclude(uint48[5] storage array, uint48 element) internal {\\n if (element == 0) {\\n revert U48L5_IllegalElement(0);\\n }\\n\\n uint256 elementIndex = LENGTH; // LENGTH is an invalid index\\n uint256 i;\\n\\n for (; i < LENGTH; i++) {\\n if (array[i] == element) {\\n // element index in the array\\n elementIndex = i;\\n }\\n if (array[i] == 0) {\\n // last non-zero element\\n i = i > 0 ? i - 1 : 0;\\n break;\\n }\\n }\\n\\n // if array is full, i == LENGTH\\n // hence swapping with element at last index\\n i = i == LENGTH ? LENGTH - 1 : i;\\n\\n if (elementIndex != LENGTH) {\\n if (i == elementIndex) {\\n // if element is last element, simply make it zero\\n array[elementIndex] = 0;\\n } else {\\n // move last to element's place and empty lastIndex slot\\n (array[elementIndex], array[i]) = (array[i], 0);\\n }\\n }\\n }\\n\\n /// @notice Returns the index of the element in the array\\n /// @param array Array to perform search on\\n /// @param element Element to search\\n /// @return index if exists or LENGTH otherwise\\n function indexOf(uint48[5] storage array, uint48 element) internal view returns (uint8) {\\n for (uint8 i; i < LENGTH; i++) {\\n if (array[i] == element) {\\n return i;\\n }\\n }\\n return LENGTH; // LENGTH is an invalid index\\n }\\n\\n /// @notice Checks whether the element exists in the array\\n /// @param array Array to perform search on\\n /// @param element Element to search\\n /// @return True if element is found, false otherwise\\n function exists(uint48[5] storage array, uint48 element) internal view returns (bool) {\\n return array.indexOf(element) != LENGTH; // LENGTH is an invalid index\\n }\\n\\n /// @notice Returns length of array (number of non-zero elements)\\n /// @param array Array to perform search on\\n /// @return Length of array\\n function numberOfNonZeroElements(uint48[5] storage array) internal view returns (uint256) {\\n for (uint8 i; i < LENGTH; i++) {\\n if (array[i] == 0) {\\n return i;\\n }\\n }\\n return LENGTH;\\n }\\n\\n /// @notice Checks whether the array is empty or not\\n /// @param array Array to perform search on\\n /// @return True if the set does not have any token position active\\n function isEmpty(uint48[5] storage array) internal view returns (bool) {\\n return array[0] == 0;\\n }\\n}\\n\",\"keccak256\":\"0x31b9d020b860bda93859895fac5cb619c791a8e370d59ebb9fa4f1d81edbc070\",\"license\":\"MIT\"},\"contracts/libraries/UniswapV3PoolHelper.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\\n\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\n/// @title UniswapV3Pool helper functions\\nlibrary UniswapV3PoolHelper {\\n using UniswapV3PoolHelper for IUniswapV3Pool;\\n\\n error UV3PH_OracleConsultFailed();\\n\\n /// @notice Get the pool's current tick\\n /// @param v3Pool The uniswap v3 pool contract\\n /// @return tick the current tick\\n function tickCurrent(IUniswapV3Pool v3Pool) internal view returns (int24 tick) {\\n (, tick, , , , , ) = v3Pool.slot0();\\n }\\n\\n /// @notice Get the pool's current sqrt price\\n /// @param v3Pool The uniswap v3 pool contract\\n /// @return sqrtPriceX96 the current sqrt price\\n function sqrtPriceCurrent(IUniswapV3Pool v3Pool) internal view returns (uint160 sqrtPriceX96) {\\n (sqrtPriceX96, , , , , , ) = v3Pool.slot0();\\n }\\n\\n /// @notice Get twap price for uniswap v3 pool\\n /// @param v3Pool The uniswap v3 pool contract\\n /// @param twapDuration The twap period\\n /// @return sqrtPriceX96 the twap price\\n function twapSqrtPrice(IUniswapV3Pool v3Pool, uint32 twapDuration) internal view returns (uint160 sqrtPriceX96) {\\n int24 _twapTick = v3Pool.twapTick(twapDuration);\\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_twapTick);\\n }\\n\\n /// @notice Get twap tick for uniswap v3 pool\\n /// @param v3Pool The uniswap v3 pool contract\\n /// @param twapDuration The twap period\\n /// @return _twapTick the twap tick\\n function twapTick(IUniswapV3Pool v3Pool, uint32 twapDuration) internal view returns (int24 _twapTick) {\\n if (twapDuration == 0) {\\n return v3Pool.tickCurrent();\\n }\\n\\n uint32[] memory secondAgos = new uint32[](2);\\n secondAgos[0] = twapDuration;\\n secondAgos[1] = 0;\\n\\n // this call will fail if period is bigger than MaxObservationPeriod\\n try v3Pool.observe(secondAgos) returns (int56[] memory tickCumulatives, uint160[] memory) {\\n int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n int24 timeWeightedAverageTick = int24(tickCumulativesDelta / int56(uint56(twapDuration)));\\n\\n // Always round to negative infinity\\n if (tickCumulativesDelta < 0 && (tickCumulativesDelta % int56(uint56(twapDuration)) != 0)) {\\n timeWeightedAverageTick--;\\n }\\n return timeWeightedAverageTick;\\n } catch {\\n // if for some reason v3Pool.observe fails, fallback to the current tick\\n (, _twapTick, , , , , ) = v3Pool.slot0();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c14ffade5bbb417584a69e08cf4005abde9af5c24e70042db815a6bad2e7b29\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/VTokenPosition.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { FundingPayment } from './FundingPayment.sol';\\nimport { LiquidityPosition } from './LiquidityPosition.sol';\\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\\n\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\n\\n/// @title VToken position functions\\nlibrary VTokenPosition {\\n using FullMath for uint256;\\n using SignedFullMath for int256;\\n using UniswapV3PoolHelper for IUniswapV3Pool;\\n\\n using LiquidityPosition for LiquidityPosition.Info;\\n using LiquidityPositionSet for LiquidityPosition.Set;\\n using Protocol for Protocol.Info;\\n\\n enum RISK_SIDE {\\n LONG,\\n SHORT\\n }\\n\\n struct Set {\\n // Fixed length array of poolId = vTokenAddress.truncate()\\n // Open positions in 8 different pairs at same time.\\n // Collision between poolId is not possible.\\n uint32[8] active; // array of poolIds\\n mapping(uint32 => VTokenPosition.Info) positions; // poolId => Position\\n int256 vQuoteBalance;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n struct Info {\\n int256 balance; // vTokenLong - vTokenShort\\n int256 netTraderPosition;\\n int256 sumALastX128;\\n // this is moved from accounts to here because of the in margin available check\\n // the loop needs to be done over liquidity positions of same token only\\n LiquidityPosition.Set liquidityPositions;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n /// @notice Gives the market value of the supplied token position\\n /// @param position token position\\n /// @param priceX128 price in Q128\\n /// @param wrapper pool wrapper corresponding to position\\n /// @return value market value with 6 decimals\\n function marketValue(\\n VTokenPosition.Info storage position,\\n uint256 priceX128,\\n IVPoolWrapper wrapper\\n ) internal view returns (int256 value) {\\n value = position.balance.mulDiv(priceX128, FixedPoint128.Q128);\\n value += unrealizedFundingPayment(position, wrapper);\\n }\\n\\n /// @notice returns the market value of the supplied token position\\n /// @param position token position\\n /// @param priceX128 price in Q128\\n /// @param poolId id of the rage trade pool\\n /// @param protocol ref to the protocol state\\n function marketValue(\\n VTokenPosition.Info storage position,\\n uint32 poolId,\\n uint256 priceX128,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 value) {\\n return marketValue(position, priceX128, protocol.vPoolWrapper(poolId));\\n }\\n\\n /// @notice returns the market value of the supplied token position\\n /// @param position token position\\n /// @param poolId id of the rage trade pool\\n /// @param protocol ref to the protocol state\\n function marketValue(\\n VTokenPosition.Info storage position,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256) {\\n uint256 priceX128 = protocol.getCachedVirtualTwapPriceX128(poolId);\\n return marketValue(position, poolId, priceX128, protocol);\\n }\\n\\n function riskSide(VTokenPosition.Info storage position) internal view returns (RISK_SIDE) {\\n return position.balance > 0 ? RISK_SIDE.LONG : RISK_SIDE.SHORT;\\n }\\n\\n /// @notice returns the vQuoteIncrease due to unrealized funding payment for the trader position (+ve means receiving and -ve means paying)\\n /// @param position token position\\n /// @param wrapper pool wrapper corresponding to position\\n /// @return unrealizedFpBill funding to be realized (+ve means receive and -ve means pay)\\n function unrealizedFundingPayment(VTokenPosition.Info storage position, IVPoolWrapper wrapper)\\n internal\\n view\\n returns (int256)\\n {\\n int256 extrapolatedSumAX128 = wrapper.getExtrapolatedSumAX128();\\n int256 vQuoteIncrease = -FundingPayment.bill(\\n extrapolatedSumAX128,\\n position.sumALastX128,\\n position.netTraderPosition\\n );\\n return vQuoteIncrease;\\n }\\n\\n /// @notice gets the account's net position for a given poolId\\n /// @param position token position\\n /// @param poolId id of the rage trade pool\\n /// @param protocol ref to the protocol state\\n /// @return net position\\n function getNetPosition(\\n VTokenPosition.Info storage position,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256) {\\n return\\n position.netTraderPosition +\\n position.liquidityPositions.getNetPosition(protocol.vPool(poolId).sqrtPriceCurrent());\\n }\\n}\\n\",\"keccak256\":\"0x9fbaf7aa199362453c1805021018327619e102df5131410a6872bea6965462fa\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/VTokenPositionSet.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\n\\nimport { AddressHelper } from './AddressHelper.sol';\\nimport { LiquidityPosition } from './LiquidityPosition.sol';\\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { PriceMath } from './PriceMath.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { SignedMath } from './SignedMath.sol';\\nimport { VTokenPosition } from './VTokenPosition.sol';\\nimport { Uint32L8ArrayLib } from './Uint32L8Array.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\nimport { IVToken } from '../interfaces/IVToken.sol';\\n\\n/// @title VToken position set functions\\nlibrary VTokenPositionSet {\\n using AddressHelper for address;\\n using FullMath for uint256;\\n using PriceMath for uint256;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n using SignedMath for int256;\\n using Uint32L8ArrayLib for uint32[8];\\n\\n using LiquidityPositionSet for LiquidityPosition.Set;\\n using Protocol for Protocol.Info;\\n using VTokenPosition for VTokenPosition.Info;\\n using VTokenPositionSet for VTokenPosition.Set;\\n\\n error VPS_IncorrectUpdate();\\n error VPS_DeactivationFailed(uint32 poolId);\\n error VPS_TokenInactive(uint32 poolId);\\n\\n /// @notice denotes token position change\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vtoken whose position was taken\\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\\n /// @param vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\\n /// @param sqrtPriceX96Start shows the sqrtPriceX96 at the start of trade execution, can be 0 if not on v3Pool\\n /// @param sqrtPriceX96End shows the sqrtPriceX96 at the end of trade execution, can be 0 if not on v3Pool\\n event TokenPositionChanged(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int256 vTokenAmountOut,\\n int256 vQuoteAmountOut,\\n uint160 sqrtPriceX96Start,\\n uint160 sqrtPriceX96End\\n );\\n\\n /// @notice denotes funding payment for a range / token position\\n /// @param accountId serial number of the account\\n /// @param poolId address of token for which funding was paid\\n /// @param amount amount of funding paid (negative) or received (positive)\\n /// @param sumALastX128 val of sum of the term A in funding payment math, when op took place\\n event TokenPositionFundingPaymentRealized(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int256 amount,\\n int256 sumALastX128\\n );\\n\\n /**\\n * Internal methods\\n */\\n\\n /// @notice activates token with address 'vToken' if not already active\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n function activate(VTokenPosition.Set storage set, uint32 poolId) internal {\\n set.active.include(poolId);\\n }\\n\\n /// @notice deactivates token with address 'vToken'\\n /// @dev ensures that the balance is 0 and there are not range positions active otherwise throws an error\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n function deactivate(VTokenPosition.Set storage set, uint32 poolId) internal {\\n if (set.positions[poolId].balance != 0 || !set.positions[poolId].liquidityPositions.isEmpty()) {\\n revert VPS_DeactivationFailed(poolId);\\n }\\n\\n set.active.exclude(poolId);\\n }\\n\\n /// @notice updates token balance, net trader position and vQuote balance\\n /// @dev realizes funding payment to vQuote balance\\n /// @dev activates the token if not already active\\n /// @dev deactivates the token if the balance = 0 and there are no range positions active\\n /// @dev IMP: ensure that the global states are updated using zeroSwap or directly through some interaction with pool wrapper\\n /// @param set VTokenPositionSet\\n /// @param balanceAdjustments platform constants\\n /// @param poolId id of the rage trade pool\\n /// @param accountId account identifier, used for emitting event\\n /// @param protocol platform constants\\n function update(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal {\\n set.realizeFundingPayment(accountId, poolId, protocol);\\n set.active.include(poolId);\\n\\n VTokenPosition.Info storage _VTokenPosition = set.positions[poolId];\\n _VTokenPosition.balance += balanceAdjustments.vTokenIncrease;\\n _VTokenPosition.netTraderPosition += balanceAdjustments.traderPositionIncrease;\\n\\n set.vQuoteBalance += balanceAdjustments.vQuoteIncrease;\\n\\n if (_VTokenPosition.balance == 0 && _VTokenPosition.liquidityPositions.active[0] == 0) {\\n set.deactivate(poolId);\\n }\\n }\\n\\n /// @notice realizes funding payment to vQuote balance\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n /// @param accountId account identifier, used for emitting event\\n /// @param protocol platform constants\\n function realizeFundingPayment(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal {\\n set.realizeFundingPayment(accountId, poolId, protocol.pools[poolId].vPoolWrapper);\\n }\\n\\n /// @notice realizes funding payment to vQuote balance\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n /// @param accountId account identifier, used for emitting event\\n /// @param wrapper VPoolWrapper to override the set wrapper\\n function realizeFundingPayment(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IVPoolWrapper wrapper\\n ) internal {\\n VTokenPosition.Info storage position = set.positions[poolId];\\n int256 extrapolatedSumAX128 = wrapper.getSumAX128();\\n\\n int256 fundingPayment = position.unrealizedFundingPayment(wrapper);\\n set.vQuoteBalance += fundingPayment;\\n\\n position.sumALastX128 = extrapolatedSumAX128;\\n\\n emit TokenPositionFundingPaymentRealized(accountId, poolId, fundingPayment, extrapolatedSumAX128);\\n }\\n\\n /// @notice swaps tokens (Long and Short) with input in token amount / vQuote amount\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param swapParams parameters for swap\\n /// @param protocol platform constants\\n /// @return vTokenAmountOut - token amount coming out of pool\\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\\n function swapToken(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.SwapParams memory swapParams,\\n Protocol.Info storage protocol\\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n return set.swapToken(accountId, poolId, swapParams, protocol.vPoolWrapper(poolId), protocol);\\n }\\n\\n /// @notice swaps tokens (Long and Short) with input in token amount\\n /// @dev activates inactive vToe\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param vTokenAmount amount of the token\\n /// @param protocol platform constants\\n /// @return vTokenAmountOut - token amount coming out of pool\\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\\n function swapTokenAmount(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n int256 vTokenAmount,\\n Protocol.Info storage protocol\\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n return\\n set.swapToken(\\n accountId,\\n poolId,\\n /// @dev 0 means no price limit and false means amount mentioned is token amount\\n IClearingHouseStructures.SwapParams({\\n amount: vTokenAmount,\\n sqrtPriceLimit: 0,\\n isNotional: false,\\n isPartialAllowed: false,\\n settleProfit: false\\n }),\\n protocol.vPoolWrapper(poolId),\\n protocol\\n );\\n }\\n\\n /// @notice swaps tokens (Long and Short) with input in token amount / vQuote amount\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param swapParams parameters for swap\\n /// @param wrapper VPoolWrapper to override the set wrapper\\n /// @param protocol platform constants\\n /// @return vTokenAmountOut - token amount coming out of pool\\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\\n function swapToken(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.SwapParams memory swapParams,\\n IVPoolWrapper wrapper,\\n Protocol.Info storage protocol\\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n IVPoolWrapper.SwapResult memory swapResult = wrapper.swap(\\n swapParams.amount < 0,\\n swapParams.isNotional ? swapParams.amount : -swapParams.amount,\\n swapParams.sqrtPriceLimit\\n );\\n\\n // change direction basis uniswap to balance increase\\n vTokenAmountOut = -swapResult.vTokenIn;\\n vQuoteAmountOut = -swapResult.vQuoteIn;\\n\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments = IClearingHouseStructures\\n .BalanceAdjustments(vQuoteAmountOut, vTokenAmountOut, vTokenAmountOut);\\n\\n set.update(accountId, balanceAdjustments, poolId, protocol);\\n\\n emit TokenPositionChanged(\\n accountId,\\n poolId,\\n vTokenAmountOut,\\n vQuoteAmountOut,\\n swapResult.sqrtPriceX96Start,\\n swapResult.sqrtPriceX96End\\n );\\n }\\n\\n /// @notice function to liquidate all liquidity positions\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param protocol platform constants\\n /// @return notionalAmountClosed - value of net token position coming out (in notional) of all the ranges closed\\n function liquidateLiquidityPositions(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n Protocol.Info storage protocol\\n ) internal returns (uint256 notionalAmountClosed) {\\n for (uint8 i = 0; i < set.active.length; i++) {\\n uint32 truncated = set.active[i];\\n if (truncated == 0) break;\\n\\n notionalAmountClosed += set.liquidateLiquidityPositions(accountId, set.active[i], protocol);\\n }\\n }\\n\\n /// @notice function to liquidate liquidity positions for a particular token\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param protocol platform constants\\n /// @return notionalAmountClosed - value of net token position coming out (in notional) of all the ranges closed\\n function liquidateLiquidityPositions(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal returns (uint256 notionalAmountClosed) {\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\\n\\n set.getTokenPosition(poolId, false).liquidityPositions.closeAllLiquidityPositions(\\n accountId,\\n poolId,\\n balanceAdjustments,\\n protocol\\n );\\n\\n set.update(accountId, balanceAdjustments, poolId, protocol);\\n\\n // returns notional value of token position closed\\n return protocol.getNotionalValue(poolId, balanceAdjustments.traderPositionIncrease);\\n }\\n\\n /// @notice function for liquidity add/remove\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param liquidityChangeParams includes tickLower, tickUpper, liquidityDelta, limitOrderType\\n /// @return vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\\n /// @return vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\\n function liquidityChange(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\\n Protocol.Info storage protocol\\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, true);\\n\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\\n\\n vTokenPosition.liquidityPositions.liquidityChange(\\n accountId,\\n poolId,\\n liquidityChangeParams,\\n balanceAdjustments,\\n protocol\\n );\\n\\n set.update(accountId, balanceAdjustments, poolId, protocol);\\n\\n if (liquidityChangeParams.closeTokenPosition && balanceAdjustments.traderPositionIncrease != 0) {\\n set.swapTokenAmount(accountId, poolId, -balanceAdjustments.traderPositionIncrease, protocol);\\n }\\n\\n return (balanceAdjustments.vTokenIncrease, balanceAdjustments.vQuoteIncrease);\\n }\\n\\n /// @notice function to remove an eligible limit order\\n /// @dev checks whether the current price is on the correct side of the range based on the type of limit order (None, Low, High)\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param tickLower lower tick index for the range\\n /// @param tickUpper upper tick index for the range\\n /// @param protocol platform constants\\n function removeLimitOrder(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n Protocol.Info storage protocol\\n ) internal {\\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, false);\\n\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\\n int24 currentTick = protocol.getVirtualCurrentTick(poolId);\\n\\n vTokenPosition.liquidityPositions.removeLimitOrder(\\n accountId,\\n poolId,\\n currentTick,\\n tickLower,\\n tickUpper,\\n balanceAdjustments,\\n protocol\\n );\\n\\n set.update(accountId, balanceAdjustments, poolId, protocol);\\n }\\n\\n function updateOpenPoolPrices(VTokenPosition.Set storage set, Protocol.Info storage protocol) internal {\\n for (uint8 i = 0; i < set.active.length; i++) {\\n uint32 poolId = set.active[i];\\n if (poolId == 0) break;\\n protocol.updatePoolPriceCache(poolId);\\n }\\n }\\n\\n /**\\n * Internal view methods\\n */\\n\\n /// @notice returns account market value of active positions\\n /// @param set VTokenPositionSet\\n /// @param protocol platform constants\\n /// @return accountMarketValue - value of all active positions\\n function getAccountMarketValue(VTokenPosition.Set storage set, Protocol.Info storage protocol)\\n internal\\n view\\n returns (int256 accountMarketValue)\\n {\\n for (uint8 i = 0; i < set.active.length; i++) {\\n uint32 poolId = set.active[i];\\n if (poolId == 0) break;\\n // IVToken vToken = protocol[poolId].vToken;\\n VTokenPosition.Info storage position = set.positions[poolId];\\n\\n (, uint256 virtualPriceX128) = protocol.getCachedTwapPricesWithDeviationCheck(poolId);\\n uint160 virtualSqrtPriceX96 = virtualPriceX128.toSqrtPriceX96();\\n //Value of token position for current vToken\\n accountMarketValue += position.marketValue(poolId, virtualPriceX128, protocol);\\n\\n //Value of all active range position for the current vToken\\n accountMarketValue += position.liquidityPositions.marketValue(virtualSqrtPriceX96, poolId, protocol);\\n }\\n\\n // Value of the vQuote token balance\\n accountMarketValue += set.vQuoteBalance;\\n }\\n\\n /// @notice gets information about the token and liquidity positions for all the pools\\n /// @param set VTokenPositionSet\\n /// @return vQuoteBalance vQuote balance for the token position\\n /// @return vTokenPositions array of vToken position\\n function getInfo(VTokenPosition.Set storage set)\\n internal\\n view\\n returns (int256 vQuoteBalance, IClearingHouseStructures.VTokenPositionView[] memory vTokenPositions)\\n {\\n vQuoteBalance = set.vQuoteBalance;\\n\\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\\n vTokenPositions = new IClearingHouseStructures.VTokenPositionView[](numberOfTokenPositions);\\n\\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\\n vTokenPositions[i].poolId = set.active[i];\\n vTokenPositions[i].balance = set.positions[set.active[i]].balance;\\n vTokenPositions[i].netTraderPosition = set.positions[set.active[i]].netTraderPosition;\\n vTokenPositions[i].sumALastX128 = set.positions[set.active[i]].sumALastX128;\\n vTokenPositions[i].liquidityPositions = set.positions[set.active[i]].liquidityPositions.getInfo();\\n }\\n }\\n\\n /// @notice returns the long and short side risk for range positions of a particular token\\n /// @param set VTokenPositionSet\\n /// @param isInitialMargin specifies to use initial margin factor (true) or maintainance margin factor (false)\\n /// @param poolId id of the rage trade pool\\n /// @param protocol platform constants\\n /// @return longSideRisk - risk if the token price goes down\\n /// @return shortSideRisk - risk if the token price goes up\\n function getLongShortSideRisk(\\n VTokenPosition.Set storage set,\\n bool isInitialMargin,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 longSideRisk, int256 shortSideRisk) {\\n VTokenPosition.Info storage position = set.positions[poolId];\\n\\n (, uint256 virtualPriceX128) = protocol.getCachedTwapPricesWithDeviationCheck(poolId);\\n uint160 virtualSqrtPriceX96 = virtualPriceX128.toSqrtPriceX96();\\n\\n uint16 marginRatio = protocol.getMarginRatioBps(poolId, isInitialMargin);\\n\\n int256 tokenPosition = position.balance;\\n int256 longSideRiskRanges = position.liquidityPositions.longSideRisk(virtualSqrtPriceX96).toInt256();\\n\\n longSideRisk = SignedMath\\n .max(position.netTraderPosition.mulDiv(virtualPriceX128, FixedPoint128.Q128) + longSideRiskRanges, 0)\\n .mulDiv(marginRatio, 1e4);\\n\\n shortSideRisk = SignedMath.max(-tokenPosition, 0).mulDiv(virtualPriceX128, FixedPoint128.Q128).mulDiv(\\n marginRatio,\\n 1e4\\n );\\n return (longSideRisk, shortSideRisk);\\n }\\n\\n /// @notice gets the net position for the given poolId\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n /// @param protocol platform constants\\n /// @return netPosition net position of the account for the pool\\n function getNetPosition(\\n VTokenPosition.Set storage set,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 netPosition) {\\n if (!set.active.exists(poolId)) return 0;\\n VTokenPosition.Info storage tokenPosition = set.positions[poolId];\\n return tokenPosition.getNetPosition(poolId, protocol);\\n }\\n\\n /// @notice returns the long and short side risk for range positions of a particular token\\n /// @param set VTokenPositionSet\\n /// @param isInitialMargin specifies to use initial margin factor (true) or maintainance margin factor (false)\\n /// @param protocol platform constants\\n /// @return requiredMargin - required margin value based on the current active positions\\n function getRequiredMargin(\\n VTokenPosition.Set storage set,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 requiredMargin) {\\n int256 longSideRiskTotal;\\n int256 shortSideRiskTotal;\\n int256 longSideRisk;\\n int256 shortSideRisk;\\n for (uint8 i = 0; i < set.active.length; i++) {\\n if (set.active[i] == 0) break;\\n uint32 poolId = set.active[i];\\n (longSideRisk, shortSideRisk) = set.getLongShortSideRisk(isInitialMargin, poolId, protocol);\\n\\n if (protocol.isPoolCrossMargined(poolId)) {\\n longSideRiskTotal += longSideRisk;\\n shortSideRiskTotal += shortSideRisk;\\n } else {\\n requiredMargin += SignedMath.max(longSideRisk, shortSideRisk);\\n }\\n }\\n\\n requiredMargin += SignedMath.max(longSideRiskTotal, shortSideRiskTotal);\\n }\\n\\n /// @notice get or create token position\\n /// @dev activates inactive vToken if isCreateNew is true else reverts\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n /// @param createNew if 'vToken' is inactive then activates (true) else reverts with TokenInactive(false)\\n /// @return position - VTokenPosition corresponding to 'vToken'\\n function getTokenPosition(\\n VTokenPosition.Set storage set,\\n uint32 poolId,\\n bool createNew\\n ) internal returns (VTokenPosition.Info storage position) {\\n if (createNew) {\\n set.activate(poolId);\\n } else if (!set.active.exists(poolId)) {\\n revert VPS_TokenInactive(poolId);\\n }\\n\\n position = set.positions[poolId];\\n }\\n\\n /// @notice returns true if the set does not have any token position active\\n /// @param set VTokenPositionSet\\n /// @return True if there are no active positions\\n function isEmpty(VTokenPosition.Set storage set) internal view returns (bool) {\\n return set.active.isEmpty();\\n }\\n\\n /// @notice returns true if range position is active for 'vToken'\\n /// @param set VTokenPositionSet\\n /// @param poolId poolId of the vToken\\n /// @return isRangeActive - True if the range position is active\\n function isTokenRangeActive(VTokenPosition.Set storage set, uint32 poolId) internal returns (bool isRangeActive) {\\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, false);\\n isRangeActive = !vTokenPosition.liquidityPositions.isEmpty();\\n }\\n}\\n\",\"keccak256\":\"0xeaad27a02472015a705f48c1c4cc42bfbac2380de5206583a8ba2fd8ad62579f\",\"license\":\"BUSL-1.1\"},\"contracts/protocol/clearinghouse/ClearingHouse.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.8.14;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\\nimport { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport { PausableUpgradeable } from '@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\n\\nimport { Account } from '../../libraries/Account.sol';\\nimport { AddressHelper } from '../../libraries/AddressHelper.sol';\\nimport { BatchedLoop } from '../../libraries/BatchedLoop.sol';\\nimport { Protocol } from '../../libraries/Protocol.sol';\\nimport { SignedMath } from '../../libraries/SignedMath.sol';\\n\\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\\nimport { IVPoolWrapper } from '../../interfaces/IVPoolWrapper.sol';\\nimport { IOracle } from '../../interfaces/IOracle.sol';\\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\\nimport { IVToken } from '../../interfaces/IVToken.sol';\\n\\nimport { IClearingHouseActions } from '../../interfaces/clearinghouse/IClearingHouseActions.sol';\\nimport { IClearingHouseStructures } from '../../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IClearingHouseEnums } from '../../interfaces/clearinghouse/IClearingHouseEnums.sol';\\nimport { IClearingHouseOwnerActions } from '../../interfaces/clearinghouse/IClearingHouseOwnerActions.sol';\\nimport { IClearingHouseSystemActions } from '../../interfaces/clearinghouse/IClearingHouseSystemActions.sol';\\n\\nimport { Governable } from '../../utils/Governable.sol';\\nimport { Multicall } from '../../utils/Multicall.sol';\\nimport { ClearingHouseView } from './ClearingHouseView.sol';\\n\\ncontract ClearingHouse is\\n IClearingHouse,\\n Multicall,\\n ClearingHouseView, // contains storage\\n Initializable, // contains storage\\n PausableUpgradeable, // contains storage\\n Governable // contains storage\\n{\\n using AddressHelper for address;\\n using AddressHelper for IERC20;\\n using AddressHelper for IVToken;\\n using SafeERC20 for IERC20;\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n\\n using Account for Account.Info;\\n using BatchedLoop for BatchedLoop.Info;\\n using Protocol for Protocol.Info;\\n\\n uint16 constant PERC_100_BPS = 10000; // 100% in basis points\\n uint16 constant PERC_10_1E5 = 10000; // 10% in base 1e5\\n\\n modifier onlyRageTradeFactory() {\\n if (rageTradeFactoryAddress != msg.sender) revert NotRageTradeFactory();\\n _;\\n }\\n\\n /**\\n SYSTEM FUNCTIONS\\n */\\n\\n function initialize(\\n address _rageTradeFactoryAddress,\\n address initialGovernance,\\n address initialTeamMultisig,\\n IERC20 _defaultCollateralToken,\\n IOracle _defaultCollateralTokenOracle,\\n IInsuranceFund _insuranceFund,\\n IVQuote _vQuote\\n ) external initializer {\\n rageTradeFactoryAddress = _rageTradeFactoryAddress;\\n protocol.settlementToken = _defaultCollateralToken;\\n insuranceFund = _insuranceFund;\\n\\n protocol.vQuote = _vQuote;\\n\\n _updateCollateralSettings(\\n _defaultCollateralToken,\\n CollateralSettings({ oracle: _defaultCollateralTokenOracle, twapDuration: 60, isAllowedForDeposit: true })\\n );\\n\\n __Governable_init(initialGovernance, initialTeamMultisig);\\n __Pausable_init_unchained();\\n }\\n\\n function registerPool(Pool calldata poolInfo) external onlyRageTradeFactory {\\n uint32 poolId = poolInfo.vToken.truncate();\\n\\n // pool will not be registered twice by the rage trade factory\\n assert(protocol.pools[poolId].vToken.isZero());\\n\\n protocol.pools[poolId] = poolInfo;\\n protocol.poolIds.push(poolId);\\n\\n emit PoolSettingsUpdated(poolId, poolInfo.settings);\\n }\\n\\n /**\\n ADMIN FUNCTIONS\\n */\\n\\n function updateCollateralSettings(IERC20 cToken, CollateralSettings memory collateralSettings)\\n external\\n onlyGovernance\\n {\\n if ((address(collateralSettings.oracle)).isZero()) revert InvalidSetting(0x10);\\n if (collateralSettings.twapDuration > 1 days) revert InvalidSetting(0x11);\\n _updateCollateralSettings(cToken, collateralSettings);\\n }\\n\\n function updatePoolSettings(uint32 poolId, PoolSettings calldata newSettings) external onlyGovernance {\\n protocol.pools[poolId].settings = newSettings;\\n if ((address(newSettings.oracle)).isZero()) revert InvalidSetting(0x20);\\n if (newSettings.twapDuration < 5 minutes || newSettings.twapDuration > 1 days) revert InvalidSetting(0x21);\\n if (newSettings.initialMarginRatioBps > PERC_100_BPS) revert InvalidSetting(0x22);\\n if (newSettings.maintainanceMarginRatioBps > PERC_100_BPS) revert InvalidSetting(0x23);\\n if (newSettings.maxVirtualPriceDeviationRatioBps > (PERC_100_BPS * 2) / 10) revert InvalidSetting(0x24);\\n\\n emit PoolSettingsUpdated(poolId, newSettings);\\n }\\n\\n function updateProtocolSettings(\\n LiquidationParams calldata _liquidationParams,\\n uint256 _removeLimitOrderFee,\\n uint256 _minimumOrderNotional,\\n uint256 _minRequiredMargin\\n ) external onlyGovernance {\\n if (_liquidationParams.rangeLiquidationFeeFraction > PERC_10_1E5) revert InvalidSetting(0x30);\\n if (_liquidationParams.tokenLiquidationFeeFraction > PERC_10_1E5) revert InvalidSetting(0x31);\\n if (_liquidationParams.closeFactorMMThresholdBps > PERC_100_BPS) revert InvalidSetting(0x32);\\n if (_liquidationParams.partialLiquidationCloseFactorBps > PERC_100_BPS) revert InvalidSetting(0x33);\\n if (_liquidationParams.insuranceFundFeeShareBps > PERC_100_BPS) revert InvalidSetting(0x34);\\n if (_liquidationParams.liquidationSlippageSqrtToleranceBps > PERC_100_BPS / 10) revert InvalidSetting(0x35);\\n if (_liquidationParams.maxRangeLiquidationFees > 1000e6) revert InvalidSetting(0x36);\\n if (_liquidationParams.minNotionalLiquidatable > 1000e6) revert InvalidSetting(0x37);\\n if (_removeLimitOrderFee > 1000e6) revert InvalidSetting(0x38);\\n if (_minimumOrderNotional > 1000e6) revert InvalidSetting(0x39);\\n if (_minRequiredMargin > 1000e6) revert InvalidSetting(0x3A);\\n\\n protocol.liquidationParams = _liquidationParams;\\n protocol.removeLimitOrderFee = _removeLimitOrderFee;\\n protocol.minimumOrderNotional = _minimumOrderNotional;\\n protocol.minRequiredMargin = _minRequiredMargin;\\n emit ProtocolSettingsUpdated(\\n _liquidationParams,\\n _removeLimitOrderFee,\\n _minimumOrderNotional,\\n _minRequiredMargin\\n );\\n }\\n\\n function pause(uint256 numberOfPoolsToUpdateInThisTx) external onlyGovernanceOrTeamMultisig whenNotPaused {\\n if (unpauseLoop.isInProgress()) revert CannotPauseIfUnpauseInProgress();\\n\\n bool completed = pauseLoop.iterate({\\n startAt: 0,\\n endBefore: protocol.poolIds.length,\\n batchSize: numberOfPoolsToUpdateInThisTx,\\n execute: _forEachPoolOnPause\\n });\\n\\n if (completed) _pause();\\n }\\n\\n function unpause(uint256 numberOfPoolsToUpdateInThisTx) external onlyGovernanceOrTeamMultisig whenPaused {\\n if (pauseLoop.isInProgress()) revert CannotUnpauseIfPauseInProgress();\\n\\n bool completed = unpauseLoop.iterate({\\n startAt: 0,\\n endBefore: protocol.poolIds.length,\\n batchSize: numberOfPoolsToUpdateInThisTx,\\n execute: _forEachPoolOnUnpause\\n });\\n\\n if (completed) _unpause();\\n }\\n\\n /// @inheritdoc IClearingHouseOwnerActions\\n function withdrawProtocolFee(uint256 numberOfPoolsToUpdateInThisTx) external {\\n withdrawProtocolFeeLoop.iterate({\\n startAt: 0,\\n endBefore: protocol.poolIds.length,\\n batchSize: numberOfPoolsToUpdateInThisTx,\\n execute: _forEachPoolOnWithdrawProtocolFee\\n });\\n }\\n\\n /**\\n USER FUNCTIONS\\n */\\n\\n /// @inheritdoc IClearingHouseActions\\n function createAccount() public whenNotPaused returns (uint256 newAccountId) {\\n newAccountId = numAccounts;\\n numAccounts = newAccountId + 1; // SSTORE\\n\\n Account.Info storage newAccount = accounts[newAccountId];\\n newAccount.owner = msg.sender;\\n newAccount.id = uint96(newAccountId);\\n\\n emit AccountCreated(msg.sender, newAccountId);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function updateMargin(\\n uint256 accountId,\\n uint32 collateralId,\\n int256 amount\\n ) public whenNotPaused {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n _updateMargin(account, collateralId, amount, amount < 0);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function createAccountAndAddMargin(uint32 collateralId, uint256 amount) external returns (uint256 newAccountId) {\\n newAccountId = createAccount();\\n updateMargin(newAccountId, collateralId, int256(amount));\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function updateProfit(uint256 accountId, int256 amount) external whenNotPaused {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n _updateProfit(account, amount, true);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function settleProfit(uint256 accountId) external whenNotPaused {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n account.settleProfit(protocol);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function swapToken(\\n uint256 accountId,\\n uint32 poolId,\\n SwapParams memory swapParams\\n ) external whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n return _swapToken(account, poolId, swapParams, true);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function updateRangeOrder(\\n uint256 accountId,\\n uint32 poolId,\\n LiquidityChangeParams calldata liquidityChangeParams\\n ) external whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n return _updateRangeOrder(account, poolId, liquidityChangeParams, true);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function removeLimitOrder(\\n uint256 accountId,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper\\n ) external {\\n _updateAccountPoolPrices(accounts[accountId]);\\n _removeLimitOrder(accountId, poolId, tickLower, tickUpper);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function liquidateLiquidityPositions(uint256 accountId) external {\\n _updateAccountPoolPrices(accounts[accountId]);\\n _liquidateLiquidityPositions(accountId);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function liquidateTokenPosition(uint256 targetAccountId, uint32 poolId) external returns (int256 keeperFee) {\\n _updateAccountPoolPrices(accounts[targetAccountId]);\\n return _liquidateTokenPosition(targetAccountId, poolId);\\n }\\n\\n /**\\n MULTICALL\\n */\\n\\n function multicallWithSingleMarginCheck(uint256 accountId, MulticallOperation[] calldata operations)\\n external\\n returns (bytes[] memory results)\\n {\\n results = new bytes[](operations.length);\\n\\n Account.Info storage account = accounts[accountId];\\n _updateAccountPoolPrices(account);\\n\\n bool checkOwner = false;\\n bool checkProfit = false;\\n bool checkMargin = false;\\n\\n for (uint256 i; i < operations.length; i++) {\\n if (operations[i].operationType == MulticallOperationType.UPDATE_MARGIN) {\\n // ADD_MARGIN\\n (uint32 collateralId, int256 amount) = abi.decode(operations[i].data, (uint32, int256));\\n checkOwner = true;\\n checkMargin = checkMargin || amount < 0;\\n _updateMargin(account, collateralId, amount, false);\\n } else if (operations[i].operationType == MulticallOperationType.UPDATE_PROFIT) {\\n // UPDATE_PROFIT\\n int256 amount = abi.decode(operations[i].data, (int256));\\n _updateProfit(account, amount, false);\\n checkOwner = true;\\n if (amount < 0) {\\n checkProfit = true;\\n checkMargin = true;\\n }\\n } else if (operations[i].operationType == MulticallOperationType.SWAP_TOKEN) {\\n // SWAP_TOKEN\\n (uint32 poolId, SwapParams memory sp) = abi.decode(operations[i].data, (uint32, SwapParams));\\n (int256 vTokenAmountOut, int256 vQuoteAmountOut) = _swapToken(account, poolId, sp, false);\\n results[i] = abi.encode(vTokenAmountOut, vQuoteAmountOut);\\n checkOwner = true;\\n checkMargin = true;\\n } else if (operations[i].operationType == MulticallOperationType.UPDATE_RANGE_ORDER) {\\n // UPDATE_RANGE_ORDER\\n (uint32 poolId, LiquidityChangeParams memory lcp) = abi.decode(\\n operations[i].data,\\n (uint32, LiquidityChangeParams)\\n );\\n (int256 vTokenAmountOut, int256 vQuoteAmountOut) = _updateRangeOrder(account, poolId, lcp, false);\\n results[i] = abi.encode(vTokenAmountOut, vQuoteAmountOut);\\n checkOwner = true;\\n checkMargin = true;\\n } else if (operations[i].operationType == MulticallOperationType.REMOVE_LIMIT_ORDER) {\\n // REMOVE_LIMIT_ORDER\\n (uint32 poolId, int24 tickLower, int24 tickUpper) = abi.decode(\\n operations[i].data,\\n (uint32, int24, int24)\\n );\\n _removeLimitOrder(accountId, poolId, tickLower, tickUpper);\\n } else if (operations[i].operationType == MulticallOperationType.LIQUIDATE_LIQUIDITY_POSITIONS) {\\n // LIQUIDATE_LIQUIDITY_POSITIONS\\n uint32 accountToLiquidate = abi.decode(operations[i].data, (uint32));\\n _liquidateLiquidityPositions(accountToLiquidate);\\n } else if (operations[i].operationType == MulticallOperationType.LIQUIDATE_TOKEN_POSITION) {\\n // LIQUIDATE_TOKEN_POSITION\\n (uint32 accountToLiquidate, uint32 poolId) = abi.decode(operations[i].data, (uint32, uint32));\\n results[i] = abi.encode(_liquidateTokenPosition(accountToLiquidate, poolId));\\n } else {\\n revert InvalidMulticallOperationType(operations[i].operationType);\\n }\\n }\\n\\n // after all the operations are done, check the margin requirements\\n if (checkOwner) _getAccountAndCheckOwner(accountId);\\n if (checkProfit) account.checkIfProfitAvailable(protocol);\\n if (checkMargin) account.checkIfMarginAvailable(true, protocol);\\n\\n return results;\\n }\\n\\n /**\\n INTERNAL HELPERS\\n */\\n\\n function _updateAccountPoolPrices(Account.Info storage account) internal {\\n account.updateAccountPoolPrices(protocol);\\n }\\n\\n function _updateMargin(\\n Account.Info storage account,\\n uint32 collateralId,\\n int256 amount,\\n bool checkMargin\\n ) internal whenNotPaused {\\n Collateral storage collateral = _checkCollateralIdAndGetInfo({\\n collateralId: collateralId,\\n isWithdraw: amount < 0\\n });\\n\\n // delegate call to account library to perform state update and emit events\\n account.updateMargin(collateralId, amount, protocol, checkMargin);\\n\\n // transfer settlement tokens between clearing house and account owner\\n if (amount > 0) {\\n collateral.token.safeTransferFrom(msg.sender, address(this), uint256(amount));\\n } else if (amount < 0) {\\n collateral.token.safeTransfer(msg.sender, uint256(-amount));\\n }\\n }\\n\\n function _updateProfit(\\n Account.Info storage account,\\n int256 amount,\\n bool checkMargin\\n ) internal whenNotPaused {\\n if (amount == 0) revert ZeroAmount();\\n\\n account.updateProfit(amount, protocol, checkMargin);\\n if (amount > 0) {\\n protocol.settlementToken.safeTransferFrom(msg.sender, address(this), uint256(amount));\\n } else {\\n protocol.settlementToken.safeTransfer(msg.sender, uint256(-amount));\\n }\\n }\\n\\n function _updateRangeOrder(\\n Account.Info storage account,\\n uint32 poolId,\\n LiquidityChangeParams memory liquidityChangeParams,\\n bool checkMargin\\n ) internal whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n _checkPoolId(poolId);\\n\\n if (liquidityChangeParams.sqrtPriceCurrent != 0) {\\n _checkSlippage(poolId, liquidityChangeParams.sqrtPriceCurrent, liquidityChangeParams.slippageToleranceBps);\\n }\\n\\n uint256 notionalValueAbs;\\n (vTokenAmountOut, vQuoteAmountOut, notionalValueAbs) = account.liquidityChange(\\n poolId,\\n liquidityChangeParams,\\n protocol,\\n checkMargin\\n );\\n\\n if (notionalValueAbs < protocol.minimumOrderNotional) revert LowNotionalValue(notionalValueAbs);\\n }\\n\\n function _swapToken(\\n Account.Info storage account,\\n uint32 poolId,\\n SwapParams memory swapParams,\\n bool checkMargin\\n ) internal whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n _checkPoolId(poolId);\\n\\n (vTokenAmountOut, vQuoteAmountOut) = account.swapToken(poolId, swapParams, protocol, checkMargin);\\n\\n uint256 vQuoteAmountOutAbs = uint256(vQuoteAmountOut.abs());\\n if (vQuoteAmountOutAbs < protocol.minimumOrderNotional) revert LowNotionalValue(vQuoteAmountOutAbs);\\n\\n if (swapParams.sqrtPriceLimit != 0 && !swapParams.isPartialAllowed) {\\n if (\\n !((swapParams.isNotional && vQuoteAmountOut.abs() == swapParams.amount.abs()) ||\\n (!swapParams.isNotional && vTokenAmountOut.abs() == swapParams.amount.abs()))\\n ) revert SlippageBeyondTolerance();\\n }\\n }\\n\\n function _liquidateLiquidityPositions(uint256 accountId) internal whenNotPaused returns (int256) {\\n Account.Info storage account = accounts[accountId];\\n\\n (int256 keeperFee, int256 insuranceFundFee, int256 accountMarketValue) = account.liquidateLiquidityPositions(\\n protocol\\n );\\n\\n int256 accountFee = keeperFee + insuranceFundFee;\\n\\n if (keeperFee <= 0) revert KeeperFeeNotPositive(keeperFee);\\n protocol.settlementToken.safeTransfer(msg.sender, uint256(keeperFee));\\n _transferInsuranceFundFee(insuranceFundFee);\\n\\n emit Account.LiquidityPositionsLiquidated(\\n accountId,\\n msg.sender,\\n accountFee,\\n keeperFee,\\n insuranceFundFee,\\n accountMarketValue\\n );\\n\\n return keeperFee;\\n }\\n\\n function _liquidateTokenPosition(uint256 accountId, uint32 poolId)\\n internal\\n whenNotPaused\\n returns (int256 keeperFee)\\n {\\n Account.Info storage account = accounts[accountId];\\n\\n _checkPoolId(poolId);\\n int256 insuranceFundFee;\\n (keeperFee, insuranceFundFee) = account.liquidateTokenPosition(poolId, protocol);\\n if (keeperFee <= 0) revert KeeperFeeNotPositive(keeperFee);\\n protocol.settlementToken.safeTransfer(msg.sender, uint256(keeperFee));\\n _transferInsuranceFundFee(insuranceFundFee);\\n }\\n\\n function _removeLimitOrder(\\n uint256 accountId,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal whenNotPaused returns (uint256 keeperFee) {\\n Account.Info storage account = accounts[accountId];\\n\\n _checkPoolId(poolId);\\n keeperFee = protocol.removeLimitOrderFee;\\n\\n account.removeLimitOrder(poolId, tickLower, tickUpper, keeperFee, protocol);\\n\\n protocol.settlementToken.safeTransfer(msg.sender, keeperFee);\\n }\\n\\n function _transferInsuranceFundFee(int256 insuranceFundFee) internal {\\n if (insuranceFundFee > 0) {\\n protocol.settlementToken.safeTransfer(address(insuranceFund), uint256(insuranceFundFee));\\n } else {\\n insuranceFund.claim(uint256(-insuranceFundFee));\\n }\\n }\\n\\n function _updateCollateralSettings(IERC20 collateralToken, CollateralSettings memory collateralSettings) internal {\\n uint32 collateralId = collateralToken.truncate();\\n\\n // doesn't allow zero address as a collateral token\\n if (collateralToken.isZero()) revert InvalidCollateralAddress(address(0));\\n\\n // doesn't allow owner to change the cToken address when updating settings, once it's truncated previously\\n if (\\n !protocol.collaterals[collateralId].token.isZero() &&\\n !protocol.collaterals[collateralId].token.eq(collateralToken)\\n ) {\\n revert IncorrectCollateralAddress(collateralToken, protocol.collaterals[collateralId].token);\\n }\\n\\n protocol.collaterals[collateralId] = Collateral(collateralToken, collateralSettings);\\n\\n emit CollateralSettingsUpdated(collateralToken, collateralSettings);\\n }\\n\\n /**\\n INTERNAL VIEW METHODS\\n */\\n\\n function _getAccountAndCheckOwner(uint256 accountId) internal view returns (Account.Info storage account) {\\n account = accounts[accountId];\\n if (msg.sender != account.owner) revert AccessDenied(msg.sender);\\n }\\n\\n function _checkCollateralIdAndGetInfo(uint32 collateralId, bool isWithdraw)\\n internal\\n view\\n returns (Collateral storage collateral)\\n {\\n collateral = protocol.collaterals[collateralId];\\n if (collateral.token.isZero()) revert CollateralDoesNotExist(collateralId);\\n // do not check if it is a withdraw operation, so that users can withdraw even if collateral is banned\\n if (!isWithdraw && !collateral.settings.isAllowedForDeposit) revert CollateralNotAllowedForUse(collateralId);\\n }\\n\\n function _checkPoolId(uint32 poolId) internal view {\\n Pool storage pool = protocol.pools[poolId];\\n if (pool.vToken.isZero()) revert PoolDoesNotExist(poolId);\\n if (!pool.settings.isAllowedForTrade) revert PoolNotAllowedForTrade(poolId);\\n }\\n\\n function _checkSlippage(\\n uint32 poolId,\\n uint160 sqrtPriceToCheck,\\n uint16 slippageToleranceBps\\n ) internal view {\\n uint160 sqrtPriceCurrent = protocol.getVirtualCurrentSqrtPriceX96(poolId);\\n uint160 diff = sqrtPriceCurrent > sqrtPriceToCheck\\n ? sqrtPriceCurrent - sqrtPriceToCheck\\n : sqrtPriceToCheck - sqrtPriceCurrent;\\n if (diff > (slippageToleranceBps * sqrtPriceToCheck) / 1e4) {\\n revert SlippageBeyondTolerance();\\n }\\n }\\n\\n /**\\n PRIVATE METHODS\\n */\\n\\n function _forEachPoolOnPause(uint256 index) private {\\n uint32 poolId = protocol.poolIds[index];\\n // account for the funding payment upto this moment before pausing\\n protocol.pools[poolId].vPoolWrapper.updateGlobalFundingState({ useZeroFundingRate: false });\\n }\\n\\n function _forEachPoolOnUnpause(uint256 index) private {\\n uint32 poolId = protocol.poolIds[index];\\n // record the funding payment as zero for the entire duration for which clearing house was paused.\\n protocol.pools[poolId].vPoolWrapper.updateGlobalFundingState({ useZeroFundingRate: true });\\n }\\n\\n function _forEachPoolOnWithdrawProtocolFee(uint256 index) private {\\n uint32 poolId = protocol.poolIds[index];\\n uint256 feeCollected = protocol.pools[poolId].vPoolWrapper.collectAccruedProtocolFee();\\n // if any protocol fee was collected then transfer to multisig\\n if (feeCollected != 0) {\\n protocol.settlementToken.safeTransfer(teamMultisig(), feeCollected);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x34083721231a6fd559eb0fc77c6bdf8e6c83bd4a5798cceb3c784b7aa6f2a004\",\"license\":\"BUSL-1.1\"},\"contracts/protocol/clearinghouse/ClearingHouseStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.8.14;\\n\\nimport { Account } from '../../libraries/Account.sol';\\nimport { BatchedLoop } from '../../libraries/BatchedLoop.sol';\\nimport { Protocol } from '../../libraries/Protocol.sol';\\n\\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\\nimport { IOracle } from '../../interfaces/IOracle.sol';\\n\\nabstract contract ClearingHouseStorage {\\n // rest slots reserved for any states from inheritance in future\\n uint256[100] private _emptySlots1;\\n\\n // at slot # 100\\n Protocol.Info internal protocol;\\n\\n uint256 public numAccounts;\\n mapping(uint256 => Account.Info) accounts;\\n\\n address public rageTradeFactoryAddress;\\n IInsuranceFund public insuranceFund;\\n\\n // progress index, used for performing for loop\\n // over an unbounded array in multiple txs\\n BatchedLoop.Info internal pauseLoop;\\n BatchedLoop.Info internal unpauseLoop;\\n BatchedLoop.Info internal withdrawProtocolFeeLoop;\\n\\n // reserved for adding slots in future\\n uint256[100] private _emptySlots2;\\n}\\n\",\"keccak256\":\"0x30e24a3572f24a033cc9ed78865bd8406191ddfbb70cc20019b68503c4d1a624\",\"license\":\"BUSL-1.1\"},\"contracts/protocol/clearinghouse/ClearingHouseView.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.8.14;\\n\\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\\nimport { IClearingHouseView } from '../../interfaces/clearinghouse/IClearingHouseView.sol';\\n\\nimport { Account } from '../../libraries/Account.sol';\\nimport { Protocol } from '../../libraries/Protocol.sol';\\n\\nimport { ClearingHouseStorage } from './ClearingHouseStorage.sol';\\n\\nimport { Extsload } from '../../utils/Extsload.sol';\\n\\nabstract contract ClearingHouseView is IClearingHouse, ClearingHouseStorage, Extsload {\\n using Account for Account.Info;\\n using Protocol for Protocol.Info;\\n\\n /// @inheritdoc IClearingHouseView\\n function getAccountMarketValueAndRequiredMargin(uint256 accountId, bool isInitialMargin)\\n public\\n view\\n returns (int256 marketValue, int256 requiredMargin)\\n {\\n (marketValue, requiredMargin) = accounts[accountId].getAccountValueAndRequiredMargin(isInitialMargin, protocol);\\n }\\n\\n /// @inheritdoc IClearingHouseView\\n function getAccountNetProfit(uint256 accountId) public view returns (int256 accountNetProfit) {\\n accountNetProfit = accounts[accountId].getAccountPositionProfits(protocol);\\n }\\n\\n /// @inheritdoc IClearingHouseView\\n function getAccountNetTokenPosition(uint256 accountId, uint32 poolId) public view returns (int256 netPosition) {\\n return accounts[accountId].getNetPosition(poolId, protocol);\\n }\\n\\n /// @inheritdoc IClearingHouseView\\n function getRealTwapPriceX128(uint32 poolId) public view returns (uint256 realPriceX128) {\\n realPriceX128 = protocol.getCachedRealTwapPriceX128(poolId);\\n }\\n\\n /// @inheritdoc IClearingHouseView\\n function getVirtualTwapPriceX128(uint32 poolId) public view returns (uint256 virtualPriceX128) {\\n virtualPriceX128 = protocol.getCachedVirtualTwapPriceX128(poolId);\\n }\\n}\\n\",\"keccak256\":\"0xbec5c93cfdf81646e4539224af0b4cb4922ab3d2e6e2523534903fd2fa6dbc11\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Extsload.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\nimport { IExtsload } from '../interfaces/IExtsload.sol';\\n\\n/// @notice Allows the inheriting contract make it's state accessable to other contracts\\n/// https://ethereum-magicians.org/t/extsload-opcode-proposal/2410/11\\nabstract contract Extsload is IExtsload {\\n function extsload(bytes32 slot) external view returns (bytes32 val) {\\n assembly {\\n val := sload(slot)\\n }\\n }\\n\\n function extsload(bytes32[] memory slots) external view returns (bytes32[] memory) {\\n assembly {\\n let end := add(0x20, add(slots, mul(mload(slots), 0x20)))\\n for {\\n let pointer := add(slots, 32)\\n } lt(pointer, end) {\\n\\n } {\\n let value := sload(mload(pointer))\\n mstore(pointer, value)\\n pointer := add(pointer, 0x20)\\n }\\n }\\n\\n return slots;\\n }\\n}\\n\",\"keccak256\":\"0xb74368b2d34810fd8f3586adfc2884fde340a89eba265456b284278ede44eed1\",\"license\":\"MIT\"},\"contracts/utils/Governable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\nimport { ContextUpgradeable } from '@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol';\\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\\n\\nimport { IGovernable } from '../interfaces/IGovernable.sol';\\n\\n/// @title Governable module that exposes onlyGovernance and onlyGovernanceOrTeamMultisig modifiers\\n/// @notice Copied and modified from @openzeppelin/contracts/access/Ownable.sol\\nabstract contract Governable is IGovernable, Initializable, ContextUpgradeable {\\n address private _governance;\\n address private _teamMultisig;\\n address private _governancePending;\\n address private _teamMultisigPending;\\n\\n event GovernanceTransferred(address indexed previousGovernance, address indexed newGovernance);\\n event TeamMultisigTransferred(address indexed previousTeamMultisig, address indexed newTeamMultisig);\\n event GovernancePending(address indexed previousGovernancePending, address indexed newGovernancePending);\\n event TeamMultisigPending(address indexed previousTeamMultisigPending, address indexed newTeamMultisigPending);\\n\\n error Unauthorised();\\n error ZeroAddress();\\n\\n /// @notice Initializes the contract setting the deployer as the initial governance and team multisig.\\n constructor() {\\n __Governable_init();\\n }\\n\\n /// @notice Useful to proxy contracts for initializing\\n function __Governable_init() internal initializer {\\n __Context_init();\\n address msgSender = _msgSender();\\n __Governable_init(msgSender, msgSender);\\n }\\n\\n /// @notice Useful to proxy contracts for initializing with custom addresses\\n /// @param initialGovernance the initial governance address\\n /// @param initialTeamMultisig the initial teamMultisig address\\n function __Governable_init(address initialGovernance, address initialTeamMultisig) internal initializer {\\n _governance = initialGovernance;\\n emit GovernanceTransferred(address(0), initialGovernance);\\n\\n _teamMultisig = initialTeamMultisig;\\n emit TeamMultisigTransferred(address(0), initialTeamMultisig);\\n }\\n\\n /// @notice Returns the address of the current governance.\\n\\n function governance() public view virtual returns (address) {\\n return _governance;\\n }\\n\\n /// @notice Returns the address of the current governance.\\n function governancePending() public view virtual returns (address) {\\n return _governancePending;\\n }\\n\\n /// @notice Returns the address of the current team multisig.transferTeamMultisig\\n function teamMultisig() public view virtual returns (address) {\\n return _teamMultisig;\\n }\\n\\n /// @notice Returns the address of the current team multisig.transferTeamMultisig\\n function teamMultisigPending() public view virtual returns (address) {\\n return _teamMultisigPending;\\n }\\n\\n /// @notice Throws if called by any account other than the governance.\\n modifier onlyGovernance() {\\n if (governance() != _msgSender()) revert Unauthorised();\\n _;\\n }\\n\\n /// @notice Throws if called by any account other than the governance or team multisig.\\n modifier onlyGovernanceOrTeamMultisig() {\\n if (teamMultisig() != _msgSender() && governance() != _msgSender()) revert Unauthorised();\\n _;\\n }\\n\\n /// @notice Initiates governance transfer to a new account (`newGovernancePending`).\\n /// @param newGovernancePending the new governance address\\n function initiateGovernanceTransfer(address newGovernancePending) external virtual onlyGovernance {\\n emit GovernancePending(_governancePending, newGovernancePending);\\n _governancePending = newGovernancePending;\\n }\\n\\n /// @notice Completes governance transfer, on being called by _governancePending.\\n function acceptGovernanceTransfer() external virtual {\\n if (_msgSender() != _governancePending) revert Unauthorised();\\n\\n emit GovernanceTransferred(_governance, _governancePending);\\n _governance = _governancePending;\\n _governancePending = address(0);\\n }\\n\\n /// @notice Initiates teamMultisig transfer to a new account (`newTeamMultisigPending`).\\n /// @param newTeamMultisigPending the new team multisig address\\n function initiateTeamMultisigTransfer(address newTeamMultisigPending)\\n external\\n virtual\\n onlyGovernanceOrTeamMultisig\\n {\\n emit TeamMultisigPending(_teamMultisigPending, newTeamMultisigPending);\\n _teamMultisigPending = newTeamMultisigPending;\\n }\\n\\n /// @notice Completes teamMultisig transfer, on being called by _teamMultisigPending.\\n function acceptTeamMultisigTransfer() external virtual {\\n if (_msgSender() != _teamMultisigPending) revert Unauthorised();\\n\\n emit TeamMultisigTransferred(_teamMultisig, _teamMultisigPending);\\n _teamMultisig = _teamMultisigPending;\\n _teamMultisigPending = address(0);\\n }\\n}\\n\",\"keccak256\":\"0x273cce59e410a4ae955fc40f202c937d2aa5bcef929c7bcd7a75ed446a12ac52\",\"license\":\"MIT\"},\"contracts/utils/Multicall.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.7.6;\\npragma abicoder v2;\\n\\nimport { IMulticall } from '@uniswap/v3-periphery/contracts/interfaces/IMulticall.sol';\\n\\n/// @title Multicall\\n/// @notice Enables calling multiple methods in a single call to the contract\\nabstract contract Multicall is IMulticall {\\n /// @inheritdoc IMulticall\\n function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) {\\n results = new bytes[](data.length);\\n for (uint256 i = 0; i < data.length; i++) {\\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\\n\\n if (!success) {\\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\\n if (result.length < 68) revert();\\n assembly {\\n result := add(result, 0x04)\\n }\\n revert(abi.decode(result, (string)));\\n }\\n\\n results[i] = result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd44030ded009dd01cd697c036595249f3c49355ceb8d37eaa2ea546eb7375f7b\",\"license\":\"GPL-2.0-or-later\"}},\"version\":1}", - "bytecode": "0x6080604052346200011b5761013d805460ff8160081c1690816000146200010c57506200002e303b1562000120565b159081620000f6575b5460ff8160081c1680156200009d57156200008e57506200005a303b1562000120565b62000066333362000184565b6200007c575b604051615f859081620002098239f35b61013d805461ff00191690556200006c565b60ff6200005a91161562000120565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b61013d805461ffff191661010117905562000037565b60ff6200002e91161562000120565b600080fd5b156200012857565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b6101a280546001600160a01b039283166001600160a01b0319918216811790925560405190936000937f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb29385939290847f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808186a31694856101a391825416179055a356fe60806040526004361015610013575b600080fd5b60003560e01c806304a6f2641461031f5780630df181ea14610316578063134015511461030d578063136439dd146103045780631e2eaeaf146102fb5780632a90b8da146102f25780633562490c146102e957806335876476146102e05780633d0aea3d146102d75780633d56a35e146102ce5780633ffe794c146102c557806340c4f69b146102bc578063424cd833146102b357806343afafba146102aa578063569634d3146102a15780635aa6e675146102985780635c975abb1461028f5780636a486482146102865780636ae732301461027d578063706bdd25146102745780637cc2f4f51461026b5780637d2efe071461026257806383d778eb146102595780638ce25a93146102505780638f24ab11146102475780638f8022bc1461023e5780639cd1be58146102355780639dca362f1461022c578063a05c8baf14610223578063ac9650d81461021a578063b790230314610211578063c7505c1514610208578063ce4c18de146101ff578063dbc0c085146101f6578063dbd035ff146101ed578063e3d41c18146101e4578063e450f6f4146101db578063e67ed1df146101d25763fabc1cbc146101ca57600080fd5b61000e6126d4565b5061000e6125fb565b5061000e61248d565b5061000e6123f9565b5061000e612362565b5061000e6122d7565b5061000e6122af565b5061000e612115565b5061000e6120ed565b5061000e61200c565b5061000e611d8c565b5061000e611d2e565b5061000e611bf7565b5061000e611b71565b5061000e61196a565b5061000e61194b565b5061000e6116ff565b5061000e611509565b5061000e6114b0565b5061000e611472565b5061000e6113be565b5061000e6112e5565b5061000e6112c0565b5061000e611297565b5061000e611269565b5061000e611221565b5061000e611096565b5061000e610b82565b5061000e610978565b5061000e610950565b5061000e6108a4565b5061000e6106a7565b5061000e6105ee565b5061000e61056e565b5061000e61054e565b5061000e61044a565b5061000e610421565b5061000e61035c565b5061000e610333565b600091031261000e57565b503461000e57600060031936011261000e5760206001600160a01b036101a55416604051908152f35b503461000e576000602060031936011261041e5761038060ff6101705416156133fd565b61038b600435615b0a565b61039481613b30565b81733FaB135e76c5c0E85A60bf50f100c8cd912f7E5691823b1561041a576044604051809481937feaf393260000000000000000000000000000000000000000000000000000000083526004830152606460248301525af4801561040d575b6103fe575b50604051f35b610407906107a7565b386103f8565b610415613795565b6103f3565b5080fd5b80fd5b503461000e57600060031936011261000e5760206001600160a01b036101a45416604051908152f35b503461000e57602060031936011261000e576001600160a01b03806101a35416331415908161053e575b506105145761017061048a60ff825416156133fd565b60d7546104ea5761049f600435606654613470565b6104a6575b005b600160ff1982546104ba60ff8216156133fd565b161790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b60046040517fd2067f43000000000000000000000000000000000000000000000000000000008152fd5b60046040517fd7a2ae6a000000000000000000000000000000000000000000000000000000008152fd5b6101a25416331415905038610474565b503461000e57602060031936011261000e57602060043554604051908152f35b503461000e57600060031936011261000e576101a48054906001600160a01b0390818316803303610514576000936101a2805492806040519685167f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808989a373ffffffffffffffffffffffffffffffffffffffff19809416179055169055f35b503461000e57600060031936011261000e576101a58054906001600160a01b0390818316803303610514576000936101a3805492806040519685167f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb28989a373ffffffffffffffffffffffffffffffffffffffff19809416179055169055f35b6001600160a01b0381160361000e57565b610124359061068d8261066e565b565b60e4359061068d8261066e565b359061068d8261066e565b503461000e5760e060031936011261000e576004356106c58161066e565b61073f6024356106d48161066e565b6044356106e08161066e565b6064356106ec8161066e565b608435906106f98261066e565b60a435926107068461066e565b60c435946107138661066e565b61013d5460ff8160081c1690816000146107835750610733303b156127a8565b15978861075657612819565b61074557005b6104a461013d61ff00198154169055565b61076b61013d61010061ff0019825416179055565b61077e61013d600160ff19825416179055565b612819565b60ff6107339116156127a8565b50634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116107bb57604052565b6107c3610790565b604052565b60a0810190811067ffffffffffffffff8211176107bb57604052565b6040810190811067ffffffffffffffff8211176107bb57604052565b6060810190811067ffffffffffffffff8211176107bb57604052565b90601f601f19910116810190811067ffffffffffffffff8211176107bb57604052565b6040519061068d826107e4565b63ffffffff81160361000e57565b8015150361000e57565b60e4359061068d8261085a565b610104359061068d8261085a565b60a4359061068d8261085a565b60c4359061068d8261085a565b359061068d8261085a565b503461000e57608060031936011261000e576004356108c28161066e565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261000e576040516104a4916060820167ffffffffffffffff811183821017610943575b60405260243561091a8161066e565b82526044356109288161084c565b60208301526064356109398161085a565b6040830152612fec565b61094b610790565b61090b565b503461000e57600060031936011261000e5760206001600160a01b0360d45416604051908152f35b503461000e5761014060031936011261000e576001600160a01b038060d454163303610a4d576109d163ffffffff6004356109b28161066e565b1691826000526064602052604060002054166001600160a01b03161590565b15610a3757610a3281610a1d610a187f4182acc9c169391ef7e765eb446fc15c9d49bc73060c678bf4c424a5c0dbdbcb9463ffffffff166000526064602052604060002090565b612c59565b610a2681612e2b565b60405191829182612ec4565b0390a1005b634e487b7160e01b600052600160045260246000fd5b60046040517f85734f31000000000000000000000000000000000000000000000000000000008152fd5b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b918091926000905b828210610ac8575011610ac1575050565b6000910152565b91508060209183015181860152018291610ab0565b90601f19601f602093610afb81518092818752878088019101610aa8565b0116010190565b602080820190808352835180925260408301928160408460051b8301019501936000915b848310610b365750505050505090565b9091929394958480610b72837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a51610add565b9801930193019194939290610b26565b503461000e5760408060031936011261000e57600480359160243567ffffffffffffffff811161000e57610bb99036908401610a77565b610bc58194929461387a565b93610bda8660005260d3602052604060002090565b95610be487613b30565b60008781938295835b818110610d5f5750505050610d4f575b50610cb8575b610c19575b815180610c158582610b02565b0390f35b733FaB135e76c5c0E85A60bf50f100c8cd912f7E5690813b1561000e5782517f998c53350000000000000000000000000000000000000000000000000000000081529081019485526001602086015260646040860152610c159490916000918391908290819060600103915af48015610cab575b15610c085780610c9f610ca5926107a7565b80610328565b38610c08565b610cb3613795565b610c8d565b733FaB135e76c5c0E85A60bf50f100c8cd912f7E56803b1561000e576000845180927f651524ed0000000000000000000000000000000000000000000000000000000082528180610d198b8983016020606491939293604081019481520152565b03915af48015610d42575b610d2f575b50610c03565b80610c9f610d3c926107a7565b38610d29565b610d4a613795565b610d24565b610d5890615b0a565b5038610bfd565b9091929693610d77610d728385876138c3565b61393a565b610d8081613928565b610dd8575080610dc0610daf610da7610d9d610dc59587896138c3565b6020810190613965565b810190613b11565b906001978015610dce575b9a614a64565b613460565b908a9291610bed565b5060008212610dba565b939650610de9610d728284866138c3565b93610df385613928565b6001948503610e425750610e16610e0e610d9d8385876138c3565b810190613b02565b93610e21858d614e4f565b6000819512610e35575b50610dc590613460565b9650869550610dc5610e2b565b6002610e55610d728486889c969c6138c3565b610e5e81613928565b03610edf575050610eb1610ebf610e768884866138c3565b610e9a8d610e94610e8c60209485810190613965565b810190613a7c565b91615162565b8c5192830191825260208201529092839160400190565b03601f19810183528261081c565b610ec9878b613a02565b52610ed4868a613a02565b50610dc58396613460565b6003610eef610d728a86886138c3565b610ef881613928565b03610f34575050610eb1610ebf610f108884866138c3565b610e9a8d610f2e610f2660209485810190613965565b810190613a57565b91614f36565b93509587610f46610d728385876138c3565b610f4f81613928565b03610f815780610f7b610f74610f6c610d9d610dc59587896138c3565b810190613a24565b91896156cf565b50613460565b6005610f91610d728385876138c3565b610f9a81613928565b03610fd05780610f7b610fcb610fc2610fba610d9d610dc596888a6138c3565b81019061145a565b63ffffffff1690565b6153b9565b6006610fe0610d728385876138c3565b610fe981613928565b036110505780610ffd610dc59284866138c3565b61103b61102963ffffffff61102261101a60209586810190613965565b8101906139b6565b911661559e565b8c519283019081528290602001610eb1565b611045828d613a02565b52610f7b818c613a02565b611063610d72611092928a948c966138c3565b92519283927f62c9ca420000000000000000000000000000000000000000000000000000000084528301613947565b0390fd5b503461000e5760208060031936011261000e5760665460d85460049283358215611218575b600090806111f55750508293915b8481106110e65750505081036110e15750600060d855005b60d855005b8060008361113e611132600261112463ffffffff61110661118799612ddd565b90549060031b1c1663ffffffff166000526064602052604060002090565b01546001600160a01b031690565b6001600160a01b031690565b86604051809481937f5e622abc0000000000000000000000000000000000000000000000000000000083525af19081156111e8575b6000916111bb575b508061118c5750613460565b6110c9565b6111b5906111a26067546001600160a01b031690565b6001600160a01b036101a3541690614b6b565b38610f7b565b6111db9150843d86116111e1575b6111d3818361081c565b810190613ef2565b3861117b565b503d6111c9565b6111f0613795565b611173565b6111ff9084613448565b905083811015611211575b93916110c9565b508261120a565b600092506110bb565b503461000e57604060031936011261000e5760206112616024356004356112478261084c565b8060005260d3845261125c6040600020613b30565b61559e565b604051908152f35b503461000e57602060031936011261000e576104a46004358060005260d3602052610fcb6040600020613b30565b503461000e57600060031936011261000e5760206001600160a01b036101a25416604051908152f35b503461000e57600060031936011261000e57602060ff61017054166040519015158152f35b503461000e57604060031936011261000e57610c156024356113068161084c565b60043560005260d360205263ffffffff604060002091604051927f7188a1ed000000000000000000000000000000000000000000000000000000008452600484015216602482015260646044820152602081606481733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af49081156113b1575b600091611393575b506040519081529081906020820190565b6113ab915060203d81116111e1576111d3818361081c565b38611382565b6113b9613795565b61137a565b503461000e57602060031936011261000e576004356113dc8161066e565b6001600160a01b03806101a354163314158061144b575b610514576000916101a59073ffffffffffffffffffffffffffffffffffffffff19838354921691826040519582167f9b068aae3039a2512c2f13bffb5fd9d95b1895b276b5c7ddf1d4fa24ec3686588888a316179055f35b5033816101a2541614156113f3565b9081602091031261000e573561146f8161084c565b90565b503461000e57602060031936011261000e5760206112616004356114958161084c565b615def565b8060020b0361000e57565b359061068d8261149a565b503461000e57608060031936011261000e576104a46004356024356114d48161084c565b604435906114e18261149a565b606435926114ee8461149a565b8060005260d36020526115046040600020613b30565b6156cf565b503461000e57606060031936011261000e576024356115278161084c565b6044356101709061153c60ff835416156133fd565b611547600435615b0a565b9161155183613b30565b60009361156560ff868512935416156133fd565b846115708383615b55565b94733FaB135e76c5c0E85A60bf50f100c8cd912f7E56803b15611678576040517ff5a284a1000000000000000000000000000000000000000000000000000000008152600481019290925263ffffffff93909316602482015260448101859052606480820152831515608482015291829060a49082905af4801561166b575b611658575b5083821315611620575061161261161b92546001600160a01b031690565b30903390614bdd565b604051f35b61162c575b5050604051f35b61164961164361165193546001600160a01b031690565b91614508565b903390614b6b565b3880611625565b80610c9f611665926107a7565b386115f4565b611673613795565b6115ef565b8280fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc60a091011261000e57604051906116b3826107c8565b8160443581526064356116c58161066e565b60208201526084356116d68161085a565b604082015260a4356116e78161085a565b6060820152608060c435916116fb8361085a565b0152565b503461000e5760e060031936011261000e5760243561171d8161084c565b6117263661167c565b809161017061173960ff825416156133fd565b61175b60ff611749600435615b0a565b9261175384613b30565b5416156133fd565b61176482615c00565b604091829161179f835195869384937f140cf61e00000000000000000000000000000000000000000000000000000000855260048501615352565b0381733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af492831561193e575b6000928394611909575b506117d484614543565b606c5481106118d757506001600160a01b036117fa60208301516001600160a01b031690565b161515806118c1575b61181a575b50519081526020810191909152604090f35b818101906118288251151590565b91826118a5575b821561186c575b5050156118435738611808565b600490517f07a1db07000000000000000000000000000000000000000000000000000000008152fd5b519091501561187a565b1590565b9081611889575b503880611836565b905061189e61189784614543565b9151614543565b1438611881565b91506118b085614543565b6118ba8251614543565b149161182f565b506118d26118766060830151151590565b611803565b82517f256d6b9a0000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b9093508161192d9293503d8411611937575b611925818361081c565b81019061533c565b91909192386117ca565b503d61191b565b611946613795565b6117c0565b503461000e57600060031936011261000e57602060d254604051908152f35b503461000e5761010060031936011261000e57600480359061198b8261084c565b60e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261000e576001600160a01b036101a254163303611b49576119ed60036119e78463ffffffff166000526064602052604060002090565b01612a7b565b611a086119fb611132612a62565b6001600160a01b03161590565b611b2b5763ffffffff61012c81611a1d612a3d565b1610908115611b15575b50611af65761ffff6127108082611a3c612a0f565b1611611ad857611a54611a4d612a1b565b61ffff1690565b11611aba576107d090611a65612a27565b1611611a9b576040517f4182acc9c169391ef7e765eb446fc15c9d49bc73060c678bf4c424a5c0dbdbcb9080610a328582612f68565b604051636a098dd160e11b815260249181019182529081906020010390fd5b604051636a098dd160e11b8152602381840190815281906020010390fd5b604051636a098dd160e11b8152602281850190815281906020010390fd5b604051636a098dd160e11b815260219181019182529081906020010390fd5b620151809150611b23612a3d565b161138611a27565b604051636a098dd160e11b8152602091810182815290918291010390fd5b6040517fd7a2ae6a000000000000000000000000000000000000000000000000000000008152fd5b503461000e57602060031936011261000e57600435611b8f8161066e565b6001600160a01b03806101a254163303610514576000916101a49073ffffffffffffffffffffffffffffffffffffffff19838354921691826040519582167f8c405decc72a19ef328c92989ce6db4e4a498e1c246413fd60997a3051ba5cff8888a316179055f35b503461000e57604060031936011261000e57602435610170611c1d60ff825416156133fd565b611c2d60ff611749600435615b0a565b8115611d0457733FaB135e76c5c0E85A60bf50f100c8cd912f7E56803b1561000e576040517fd25c4a6f000000000000000000000000000000000000000000000000000000008152600481019290925260248201839052606460448301819052600190830152600090829060849082905af48015611cf7575b611ce4575b506000811315611ccb576104a4906116126067546001600160a01b031690565b6104a4906116496116436067546001600160a01b031690565b80610c9f611cf1926107a7565b38611cab565b611cff613795565b611ca6565b60046040517f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b503461000e57600060031936011261000e5760206112616136c0565b60031961010091011261000e57600490565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc61010091011261000e57604490565b503461000e5761016060031936011261000e57611da836611d4a565b610104356101243591610144356001600160a01b036101a254163303610514576127109361ffff8581611dda86612a33565b1611611ff35785611df0611a4d60208701612a33565b11611fda5760409580611e07611a4d898801612a33565b11611fc25780611e1c611a4d60608801612a33565b11611faa57611e30611a4d60808701612a33565b11611f92576103e890611e4560a08601612a33565b1611611f7a57633b9aca008067ffffffffffffffff611e6660c087016130a4565b1611611f625780611e89611e7c60e087016130a4565b67ffffffffffffffff1690565b11611f4a57808511611f3257808211611f1a578211611f025791611efc60009594927f697aec6e94e319190380ab0f1f10018d81b64da2479eb874be92c9a733e0a83794611ed6846130ae565b611edf85606b55565b611ee881606c55565b611ef182606a55565b865194859485613311565b0390a151f35b8451636a098dd160e11b8152603a6004820152602490fd5b8551636a098dd160e11b815260396004820152602490fd5b8551636a098dd160e11b815260386004820152602490fd5b8551636a098dd160e11b815260376004820152602490fd5b8551636a098dd160e11b815260366004820152602490fd5b8451636a098dd160e11b815260356004820152602490fd5b8551636a098dd160e11b815260346004820152602490fd5b8651636a098dd160e11b815260336004820152602490fd5b8651636a098dd160e11b815260326004820152602490fd5b604051636a098dd160e11b815260316004820152602490fd5b604051636a098dd160e11b815260306004820152602490fd5b50602060031936011261000e576004803567ffffffffffffffff811161000e576120399036908301610a77565b906120438261387a565b9160005b81811061205c5760405180610c158682610b02565b60008061206a838587615eb8565b6040939161207c855180938193615ee2565b0390305af49061208a614dce565b918290156120b3575050906120ae916120a38287613a02565b52610f7b8186613a02565b612047565b826044899394511061000e5761109291836120d8920160248091518301019101615ef0565b925192839262461bcd60e51b84528301614dfe565b503461000e57600060031936011261000e5760206001600160a01b0360d55416604051908152f35b503461000e5761014060031936011261000e576024356121348161084c565b606061213f36611d5c565b916101709261215260ff855416156133fd565b61217f60ff612176612165600435615b0a565b9361216f85613b30565b36906137bd565b955416156133fd565b61218882615c00565b828401516001600160a01b03168061228f575b506121d360405194859384937fc27789d100000000000000000000000000000000000000000000000000000000855260048501615050565b0381733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af48015612282575b6000908192829161224e575b50606c54811061221b5750604080519182526020820192909252f35b6040517f256d6b9a0000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b915050612272915060603d811161227b575b61226a818361081c565b810190615028565b919091386121ff565b503d612260565b61228a613795565b6121f3565b6122a9906122a2608087015161ffff1690565b9084615cdd565b3861219b565b503461000e57602060031936011261000e5760206112616004356122d28161084c565b615e4d565b503461000e57600060031936011261000e5760206001600160a01b036101a35416604051908152f35b60209067ffffffffffffffff811161231a575b60051b0190565b612322610790565b612313565b6020908160408183019282815285518094520193019160005b82811061234e575050505090565b835185529381019392810192600101612340565b503461000e5760208060031936011261000e5760043567ffffffffffffffff811161000e573660238201121561000e578060040135906123a182612300565b916123af604051938461081c565b80835260248484019160051b8301019136831161000e57602401905b8282106123ea57610c156123de85615e8f565b60405191829182612327565b813581529084019084016123cb565b503461000e57602060031936011261000e5760043560005260d3602052610c156040600020604051907fc4b22b86000000000000000000000000000000000000000000000000000000008252600482015260646024820152602081604481733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af49081156113b15760009161139357506040519081529081906020820190565b503461000e57604060031936011261000e576004356124ab8161084c565b602435906124b76136c0565b90610170926124ca60ff855416156133fd565b6124d383615b0a565b936124dd85613b30565b6124ef60ff60008412925416156133fd565b6124f98184615b55565b92733FaB135e76c5c0E85A60bf50f100c8cd912f7E5690813b1561000e576040517ff5a284a1000000000000000000000000000000000000000000000000000000008152600481019790975263ffffffff166024870152604486018390526064808701528115156084870152610c159590600090829060a49082905af480156125ee575b6125db575b5060008213156125b157506116126125a192546001600160a01b031690565b6040519081529081906020820190565b6125bd575b50506125a1565b6116496116436125d493546001600160a01b031690565b38806125b6565b80610c9f6125e8926107a7565b38612582565b6125f6613795565b61257d565b503461000e5760408060031936011261000e5760243561261a8161085a565b60043560005260d360205281600020908251917f0c6d7f34000000000000000000000000000000000000000000000000000000008352600483015215156024820152606460448201528181606481733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af49182156126c7575b60009182936126a25750519081526020810191909152604090f35b816126bf929450610c1593503d851161193757611925818361081c565b929091611808565b6126cf613795565b612687565b503461000e57602060031936011261000e576001600160a01b03806101a354163314159081612798575b506105145761017061271360ff825416613675565b60d65461276e5761272860043560665461358a565b61272e57005b60ff19815461273f60ff8216613675565b1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b60046040517ffc23b9cd000000000000000000000000000000000000000000000000000000008152fd5b6101a254163314159050386126fe565b156127af57565b608460405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b93916128b87f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb2936000958694986001600160a01b039a8b80928173ffffffffffffffffffffffffffffffffffffffff199c168c60d454161760d4558185168c6067541617606755168a60d554161760d5551688606854161760685589604051926128a284610800565b168252603c602083015260016040830152615942565b61013d9680885460ff8160081c169081861461297057506128da303b156127a8565b159788612943575b16916101a2838882541617905560405192847f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808186a31694856101a391825416179055a3612934575b5061068d61297d565b61ff001981541690553861292b565b61295861013d61010061ff0019825416179055565b61296b61013d600160ff19825416179055565b6128e2565b60ff6128da9116156127a8565b60ff61013d5460081c16156129995761017060ff198154169055565b608460405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152fd5b61ffff81160361000e57565b60243561146f81612a03565b60443561146f81612a03565b60643561146f81612a03565b3561146f81612a03565b60843561146f8161084c565b60e43561146f8161085a565b6101043561146f8161085a565b60e43561146f8161066e565b6101243561146f8161066e565b61068d90612abd602435612a8e81612a03565b829061ffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000825416179055565b612b01604435612acc81612a03565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff1660109190911b63ffff000016178255565b612b47606435612b1081612a03565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff1660209190911b65ffff0000000016178255565b608435612b538161084c565b7fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff69ffffffff00000000000083549260301b169116178155612bd660a435612b9a8161085a565b82547fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff1690151560501b6aff0000000000000000000016178255565b612c2260c435612be58161085a565b82547fffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffff1690151560581b6bff000000000000000000000016178255565b60e43590612c2f8261066e565b906bffffffffffffffffffffffff6bffffffffffffffffffffffff1983549260601b169116179055565b600361068d91612c97600435612c6e8161066e565b82906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b612cd2602435612ca68161066e565b60018301906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b612d0d604435612ce18161066e565b60028301906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b01612d1d606435612a8e81612a03565b612d2c608435612acc81612a03565b612d3b60a435612b1081612a03565b60c435612d478161084c565b7fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff69ffffffff00000000000083549260301b169116178155612d8a612b9a612a49565b612d95612be5612a55565b612d9d612a6e565b6bffffffffffffffffffffffff6bffffffffffffffffffffffff1983549260601b169116179055565b50634e487b7160e01b600052603260045260246000fd5b90606654821015612e1e575b6066600052601c8260031c7f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354019260021b1690565b612e26612dc6565b612de9565b6066549068010000000000000000821015612eac575b6001820180606655821015612e9f575b60666000528160031c7f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354019160e083549160051b169163ffffffff9283811b93849216901b16911916179055565b612ea7612dc6565b612e51565b612eb4610790565b612e41565b359061068d82612a03565b63ffffffff91821681526101008101929161068d9190606435612ee681612a03565b61ffff809116602084015280608435612efe81612a03565b16604084015260a435612f1081612a03565b16606083015260c435612f228161084c565b166080820152612f3c612f33610864565b151560a0830152565b612f50612f47610871565b151560c0830152565b60e0612f5a61067f565b6001600160a01b0316910152565b63ffffffff91821681526101008101929161068d9190602435612f8a81612a03565b61ffff809116602084015280604435612fa281612a03565b166040840152606435612fb481612a03565b166060830152608435612fc68161084c565b166080820152612fd7612f3361087f565b612fe2612f4761088c565b60e0612f5a61068f565b906001600160a01b03806101a254163303610514578151161561304b576201518063ffffffff613023602084015163ffffffff1690565b16116130325761068d91615942565b604051636a098dd160e11b815260116004820152602490fd5b604051636a098dd160e11b815260106004820152602490fd5b50634e487b7160e01b600052601160045260246000fd5b50634e487b7160e01b600052601260045260246000fd5b67ffffffffffffffff81160361000e57565b3561146f81613092565b6132b860e061068d9261ffff81356130c581612a03565b167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00006069541617606955613136602082013561310081612a03565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff63ffff00006069549260101b16911617606955565b61317f604082013561314781612a03565b7fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff65ffff000000006069549260201b16911617606955565b606081013561318d81612a03565b7fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff67ffff0000000000006069549260301b169116176069556132106131d460808301612a33565b7fffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff69ffff00000000000000006069549260401b16911617606955565b61325d61321f60a08301612a33565b7fffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffff6bffff000000000000000000006069549260501b16911617606955565b6132b261326c60c083016130a4565b7fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff73ffffffffffffffff0000000000000000000000006069549260601b16911617606955565b016130a4565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff00000000000000000000000000000000000000006069549260a01b16911617606955565b359061068d82613092565b90949392610140926133ed6133dc60e0610160860199803561333281612a03565b61ffff8091168852602082013561334881612a03565b16602088015261336861335d60408301612eb9565b61ffff166040890152565b61338261337760608301612eb9565b61ffff166060890152565b61339c61339160808301612eb9565b61ffff166080890152565b6133b66133ab60a08301612eb9565b61ffff1660a0890152565b6133d66133c560c08301613306565b67ffffffffffffffff1660c0890152565b01613306565b67ffffffffffffffff1660e0850152565b6101008301526101208201520152565b1561340457565b606460405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152fd5b81198111613454570190565b61345c613064565b0190565b6001906000198114613454570190565b60d65492918315613581575b6000908061355f57505080925b8381106134a7575082149182156134a25750600060d655565b60d655565b63ffffffff6134b582612ddd565b90549060031b1c1660005260646020526040906134e3611132600284600020016001600160a01b0390541690565b803b1561000e576000613540935180927f5124033600000000000000000000000000000000000000000000000000000000825281838161352b60048201906000602083019252565b03925af18015613552575b6135455750613460565b613489565b80610c9f6111b5926107a7565b61355a613795565b613536565b6135699085613448565b90508181101561357a575b92613489565b5080613574565b6000935061347c565b60d7549291831561366c575b6000908061364a57505080925b8381106135c1575082149182156135bc5750600060d755565b60d755565b63ffffffff6135cf82612ddd565b90549060031b1c1660005260646020526040906001600160a01b03600283600020015416803b1561000e576000809160246136459551809481937f51240336000000000000000000000000000000000000000000000000000000008352600160048401525af18015613552576135455750613460565b6135a3565b6136549085613448565b905081811015613665575b926135a3565b508061365f565b60009350613596565b1561367c57565b606460405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152fd5b6136d060ff6101705416156133fd565b60d2547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8111613788575b6001810160d255600081815260d36020526040902080546bffffffffffffffffffffffff163360601b6bffffffffffffffffffffffff19161781556bffffffffffffffffffffffff82166bffffffffffffffffffffffff198254161790556040518181527f7325fb14450d3e5eb288c620b4ff1d6b43a41b33b4a4f143ae88cd4c12f99ea360203392a290565b613790613064565b6136fb565b506040513d6000823e3d90fd5b359081600f0b820361000e57565b3590600382101561000e57565b809291610100918291031261000e5760405190810181811067ffffffffffffffff82111761386d575b60405260e06138688183956137fa816114a5565b8552613808602082016114a5565b6020860152613819604082016137a2565b604086015261382a6060820161069c565b606086015261383b60808201612eb9565b608086015261384c60a08201610899565b60a086015261385d60c082016137b0565b60c086015201610899565b910152565b613875610790565b6137e6565b9061388482612300565b613891604051918261081c565b828152601f196138a18294612300565b019060005b8281106138b257505050565b8060606020809385010152016138a6565b9190811015613904575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561000e570190565b61390c612dc6565b6138cd565b50634e487b7160e01b600052602160045260246000fd5b6007111561393257565b61068d613911565b35600781101561000e5790565b91906020830192600782101561395a5752565b613962613911565b52565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e5760200191813603831361000e57565b919082604091031261000e57602082356139cf8161084c565b92013561146f8161084c565b6020908051156139e9570190565b61345c612dc6565b6040908051600110156139e9570190565b6020918151811015613a17575b60051b010190565b613a1f612dc6565b613a0f565b9081606091031261000e578035613a3a8161084c565b9160406020830135613a4b8161149a565b92013561146f8161149a565b91906101208382031261000e5761146f9060208435613a758161084c565b94016137bd565b809291039160c0831261000e5760a0601f198235613a998161084c565b94011261000e5760a060405191613aaf836107c8565b602081013583526040810135613ac48161066e565b60208401526060810135613ad78161085a565b60408401526080810135613aea8161085a565b60608401520135613afa8161085a565b608082015290565b9081602091031261000e573590565b919082604091031261000e5760208235613b2a8161084c565b92013590565b60005b60088060ff83161015613b9257811015613b97575b63ffffffff60018260031c8401015460e08360051b161c16908115613b9257613b72600192613c1c565b60ff809116908114613b85575b01613b33565b613b8d613064565b613b7f565b505050565b613b9f612dc6565b613b48565b60008212827f8000000000000000000000000000000000000000000000000000000000000000018212811516613c0f575b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01821316613c03570390565b613c0b613064565b0390565b613c17613064565b613bd5565b613c24613f01565b613c3e8263ffffffff16600052606d602052604060002090565b805463ffffffff838116911614613b9257613c5883614403565b613c69613c6485614022565b613fad565b937c010000000000000000000000000000000000000000000000000000000080831090811591613e35575b50613e2e5761068d94613d49613d4e613dcf94613cd56003613cc9613d9a9763ffffffff166000526064602052604060002090565b015460201c61ffff1690565b613cf561ffff613ced613ce88886613ba4565b614543565b921683613e40565b1015613dff57613d49600188017c01000000000000000000000000000000000000000000000000000000007fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff825416179055565b614492565b60018601907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000825416179055565b825463ffffffff1660209190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016178255565b9063ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055565b613d49600188017fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8154169055565b5050505050565b905085101538613c94565b9060001981830981830291828083109203918083039214613e9d57612710908282111561000e577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b505061271091500490565b6000198282099082810292838084109303928084039314613ee95768010000000000000000918383111561000e570990828211900360c01b910360401c1790565b50505060401c90565b9081602091031261000e575190565b61a4b146148015613fa1575b8015613f95575b15613f8b5763ffffffff6040517fa3b1b31d00000000000000000000000000000000000000000000000000000000815260208160048160645afa908115613f7e575b600091613f6257501690565b613f7a915060203d81116111e1576111d3818361081c565b1690565b613f86613795565b613f56565b63ffffffff431690565b5062066eec4614613f14565b5062066eeb4614613f0d565b6001600160a01b03166401000276a381108015614004575b613fd3578061146f91613ea8565b602490604051907f5d236c450000000000000000000000000000000000000000000000000000000082526004820152fd5b5073fffd8963efd1fc6a506488495d951d5263988d26811015613fc5565b61403c9063ffffffff166000526064602052604060002090565b60036140666001600160a01b0392836001820154169063ffffffff938491015460301c169061484c565b60020b9060008212156143fd5781600003915b620d89e883116143d35760018316156143aa5770ffffffffffffffffffffffffffffffffff6ffffcb933bd6fad37aa2d162d1a5940015b16926002811661438e575b60048116614372575b60088116614356575b6010811661433a575b6020811661431e575b60408116614302575b6080908181166142e7575b61010081166142cc575b61020081166142b1575b6104008116614296575b610800811661427b575b6110008116614260575b6120008116614245575b614000811661422a575b618000811661420f575b6201000081166141f4575b6202000081166141da575b6204000081166141c0575b62080000166141a5575b50600012614195575b811661418c5760ff60005b169060201c011690565b60ff6001614182565b9061419f90614558565b90614177565b6b048a170391f7dc42444e8fa26000929402901c929061416e565b6d2216e584f5fa1ea926041bedfe98909402811c93614164565b936e5d6af8dedb81196699c329225ee60402811c93614159565b936f09aa508b5b7a84e1c677de54f3e99bc902811c9361414e565b936f31be135f97d08fd981231505542fcfa602811c93614143565b936f70d869a156d2a1b890bb3df62baf32f702811c93614139565b936fa9f746462d870fdf8a65dc1f90e061e502811c9361412f565b936fd097f3bdfd2022b8845ad8f792aa582502811c93614125565b936fe7159475a2c29b7443b29c7fa6e889d902811c9361411b565b936ff3392b0822b70005940c7a398e4b70f302811c93614111565b936ff987a7253ac413176f2b074cf7815e5402811c93614107565b936ffcbe86c7900a88aedcffc83b479aa3a402811c936140fd565b936ffe5dee046a99a2a811c461f1969c305302811c936140f3565b926fff2ea16466c96a3843ec78b326b528610260801c926140e8565b926fff973b41fa98c081472e6896dfb254c00260801c926140df565b926fffcb9843d60f6159c9db58835c9266440260801c926140d6565b926fffe5caca7e10e4e61c3624eaa0941cd00260801c926140cd565b926ffff2e50f5f656932ef12357cf3c7fdcc0260801c926140c4565b926ffff97272373d413259a46990580e213a0260801c926140bb565b70ffffffffffffffffffffffffffffffffff7001000000000000000000000000000000006140b0565b60046040517f2bc80f3a000000000000000000000000000000000000000000000000000000008152fd5b81614079565b63ffffffff80911660005260646020526020600360406000200154916024604051809481937fdd86c1010000000000000000000000000000000000000000000000000000000083528160301c16600483015260601c5afa908115614485575b60009161446d575090565b61146f915060203d81116111e1576111d3818361081c565b61448d613795565b614462565b7c010000000000000000000000000000000000000000000000000000000081116144d7577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b602490604051907f1ba344530000000000000000000000000000000000000000000000000000000082526004820152fd5b7f80000000000000000000000000000000000000000000000000000000000000008114614536575b60000390565b61453e613064565b614530565b600081131561454f5790565b61146f90614508565b8015614566575b6000190490565b61456e61307b565b61455f565b6040519061458082610800565b600282526040366020840137565b81601f8201121561000e578051916145a583612300565b926145b3604051948561081c565b808452602092838086019260051b82010192831161000e578301905b8282106145dd575050505090565b83809183516145eb8161066e565b8152019101906145cf565b91909160408184031261000e5780519267ffffffffffffffff9384811161000e5782019381601f8601121561000e5784519461463186612300565b9061463f604051928361081c565b868252602096878084019160051b8301019185831161000e578801905b82821061467b575050509483015190811161000e5761146f920161458e565b81518060060b810361000e57815290880190880161465c565b6020908160408183019282815285518094520193019160005b8281106146bb575050505090565b835163ffffffff16855293810193928101926001016146ad565b60060b9060060b9060008212827fffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000018212811516614723575b82667fffffffffffff01821316613c03570390565b61472b613064565b61470e565b60060b9060060b90811561477c575b60001982147fffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000821416614770570590565b614778613064565b0590565b61478461307b565b61473f565b9060060b90811561479c575b60060b0790565b6147a461307b565b614795565b6000199060020b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000008114613454570190565b908160e091031261000e5780516147f18161066e565b9160208201516148008161149a565b91604081015161480f81612a03565b91606082015161481e81612a03565b91608081015161482d81612a03565b9160a082015160ff8116810361000e5760c09092015161146f8161085a565b9063ffffffff81168015614a04576148cb6001600160a01b0393614886614871614573565b9461487b866139db565b9063ffffffff169052565b600094859182614895876139f1565b521693604051809381927f883bdbfd00000000000000000000000000000000000000000000000000000000835260048301614694565b0381865afa8491816149df575b5061496057505060e0600491604051928380927f3850c7bd0000000000000000000000000000000000000000000000000000000082525afa918215614953575b91614921575090565b614942915060e03d811161494c575b61493a818361081c565b8101906147db565b5050505050905090565b503d614930565b61495b613795565b614918565b61498b91925061498561497861497f614978846139f1565b5160060b90565b926139db565b906146d5565b9060060b6149a261499c8284614730565b60020b90565b928260060b1291826149c1575b50506149b85790565b61146f906147a9565b6149d69250906149d091614789565b60060b90565b151538806149af565b6149fc9192503d8087833e6149f4818361081c565b8101906145f6565b5090386148d8565b505061146f9060e06001600160a01b03916004604051809481937f3850c7bd000000000000000000000000000000000000000000000000000000008352165afa908115614a57575b600091614921575090565b614a5f613795565b614a4c565b919091614a7760ff6101705416156133fd565b6000821290614a868285615b55565b93733FaB135e76c5c0E85A60bf50f100c8cd912f7E5691823b1561000e576040517ff5a284a1000000000000000000000000000000000000000000000000000000008152600481019190915263ffffffff919091166024820152604481018490526064808201526000608482018190529091829060a49082905af48015614b5e575b614b4b575b506000821315614b2c575061161261068d92546001600160a01b031690565b614b34575050565b61164961164361068d93546001600160a01b031690565b80610c9f614b58926107a7565b38614b0d565b614b66613795565b614b08565b61068d926001600160a01b03604051937fa9059cbb0000000000000000000000000000000000000000000000000000000060208601521660248401526044830152604482526080820182811067ffffffffffffffff821117614bd0575b604052614cfc565b614bd8610790565b614bc8565b909261068d93604051937f23b872dd0000000000000000000000000000000000000000000000000000000060208601526001600160a01b03809216602486015216604484015260648301526064825260a0820182811067ffffffffffffffff821117614bd057604052614cfc565b601f19601f60209267ffffffffffffffff8111614c69575b01160190565b614c71610790565b614c63565b9081602091031261000e575161146f8161085a565b15614c9257565b608460405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6001600160a01b03169060405190614d13826107e4565b6020928383527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656484840152803b15614d8a5760008281928287614d659796519301915af1614d5f614dce565b90614e0f565b80519081614d7257505050565b8261068d93614d85938301019101614c76565b614c8b565b6064846040519062461bcd60e51b82526004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b3d15614df9573d90614ddf82614c4b565b91614ded604051938461081c565b82523d6000602084013e565b606090565b90602061146f928181520190610add565b90919015614e1b575090565b815115614e2b5750805190602001fd5b6110929060405191829162461bcd60e51b8352602060048401526024830190610add565b614e5f60ff6101705416156133fd565b8115611d0457733FaB135e76c5c0E85A60bf50f100c8cd912f7E56803b1561000e576040517fd25c4a6f000000000000000000000000000000000000000000000000000000008152600481019290925260248201839052606460448301819052600090830181905290829060849082905af48015614f29575b614f16575b506000811315614efd5761068d906116126067546001600160a01b031690565b61068d906116496116436067546001600160a01b031690565b80610c9f614f23926107a7565b38614edd565b614f31613795565b614ed8565b90606091939293614f4d60ff6101705416156133fd565b614f5682615c00565b828501516001600160a01b03168061500f575b50614fa160405195869384937fc27789d1000000000000000000000000000000000000000000000000000000008552600485016150f7565b0381733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af48015615002575b60009081938291614fdc575b50606c54811061221b57509190565b915050614ff891925060603d811161227b5761226a818361081c565b9291909238614fcd565b61500a613795565b614fc1565b615022906122a2608088015161ffff1690565b38614f69565b9081606091031261000e578051916040602083015192015190565b90600382101561395a5752565b6150e860e061016093969563ffffffff61068d966101808601998652166020850152805160020b6040850152602081015160020b60608501526040810151600f0b60808501526150b0606082015160a08601906001600160a01b03169052565b608081015161ffff1660c085015260a08101511515848301526150dc60c0820151610100860190615043565b01511515610120830152565b60646101408201520160019052565b61515660e061016093969563ffffffff6000966101808601998652166020850152805160020b6040850152602081015160020b60608501526040810151600f0b60808501526150b0606082015160a08601906001600160a01b03169052565b60646101408201520152565b908293929161517760ff6101705416156133fd565b61518082615c00565b6040918291615219835195869384937f140cf61e00000000000000000000000000000000000000000000000000000000855260048501608061010092959463ffffffff6000956101208501988552166020840152805160408401526001600160a01b03602082015116606084015260408101511515828401526060810151151560a08401520151151560c0820152606460e08201520152565b0381733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af493841561532f575b600092839561530a575b5061524e85614543565b606c5481106118d757506001600160a01b0361527460208301516001600160a01b031690565b161515806152f4575b615288575b50509190565b818101906152968251151590565b91826152d8575b82156152b1575b5050156118435780615282565b51159150816152c3575b5038806152a4565b90506152d161189784614543565b14386152bb565b91506152e386614543565b6152ed8251614543565b149161529d565b506153056118766060830151151590565b61527d565b909450816153259293503d841161193757611925818361081c565b9190919338615244565b615337613795565b61523a565b919082604091031261000e576020825192015190565b608061010092959463ffffffff61068d956101208501988552166020840152805160408401526001600160a01b03602082015116606084015260408101511515828401526060810151151560a08401520151151560c0820152606460e08201520160019052565b6153c960ff6101705416156133fd565b61542360606153e28360005260d3602052604060002090565b604051809381927fdf19bf09000000000000000000000000000000000000000000000000000000008352600483016020606491939293604081019481520152565b0381733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af4918215615525575b600092839284916154ff575b5061545b8385615532565b9260008513156154cd57907f688f0846fe2852572c467d5e769db101b0fea55e8849406d85c9fb322b95299b916154a58661549e6067546001600160a01b031690565b3390614b6b565b6154ae816157bf565b604080519586526020860187905285015260608401523392608090a390565b6040517fef37dcc700000000000000000000000000000000000000000000000000000000815260048101869052602490fd5b9193505061551b915060603d811161227b5761226a818361081c565b9192909138615450565b61552d613795565b615444565b60008112817f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038313811516615591575b817f800000000000000000000000000000000000000000000000000000000000000003831216613454570190565b615599613064565b615563565b61561d916155c86040926155b860ff6101705416156133fd565b60005260d3602052604060002090565b6155d182615c00565b825193849283927fec1464960000000000000000000000000000000000000000000000000000000084526004840160409063ffffffff6064939594606083019683521660208201520152565b0381733FaB135e76c5c0E85A60bf50f100c8cd912f7E565af480156156c2575b60009182916156a2575b5060008213156156705761146f9061566b8361549e6067546001600160a01b031690565b6157bf565b6040517fef37dcc700000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b90506156bc915060403d811161193757611925818361081c565b38615647565b6156ca613795565b61563d565b929091926156e360ff6101705416156133fd565b60005260d36020526040600020916156fa81615c00565b606b5493733FaB135e76c5c0E85A60bf50f100c8cd912f7E5693843b1561000e5763ffffffff9460009460c49360405197889687957fe0448f0a000000000000000000000000000000000000000000000000000000008752600487015216602485015260020b604484015260020b6064830152866084830152606460a48301525af480156157b2575b61579f575b5061146f8161549e6067546001600160a01b031690565b80610c9f6157ac926107a7565b38615788565b6157ba613795565b615783565b60008113156157e45761068d906001600160a01b0380606754169060d5541690614b6b565b6157f96001600160a01b0360d5541691614508565b813b1561000e576000916024839260405194859384927f379607f500000000000000000000000000000000000000000000000000000000845260048401525af18015615850575b6158475750565b61068d906107a7565b615858613795565b615840565b6158ce602060016001600160a01b039361589d8587511682906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b019301519182511683906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b6020810151907fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff77ffffffff000000000000000000000000000000000000000078ff00000000000000000000000000000000000000000000000060408654940151151560c01b169360a01b16911617179055565b919063ffffffff83166001600160a01b03841615615ad85761598a6118766119fb61597d8463ffffffff166000526065602052604060002090565b546001600160a01b031690565b80615a9d575b615a3d57926159f47f52983c04d8ccd4808cd0fcb24e6e48106ecb41e803d6270c6c94a15e3ebd08d293946159ef6159c661083f565b6001600160a01b03851681529185602084015263ffffffff166000526065602052604060002090565b61585d565b615a3860405192839283909291604060609160808401956001600160a01b038091168552815116602085015263ffffffff6020820151168285015201511515910152565b0390a1565b615a5b61597d859263ffffffff166000526065602052604060002090565b6040517fa5d4d0b50000000000000000000000000000000000000000000000000000000081526001600160a01b03928316600482015291166024820152604490fd5b50615ad361187685615ac261597d8563ffffffff166000526065602052604060002090565b6001600160a01b0390811691161490565b615990565b6040517f76d8a93100000000000000000000000000000000000000000000000000000000815260006004820152602490fd5b60005260d3602052604060002090815460601c3303615b2557565b60246040517f0504a20d000000000000000000000000000000000000000000000000000000008152336004820152fd5b63ffffffff90929192168060005260656020526040600020926001600160a01b0384541615615bcf571580615bbd575b615b8c5750565b602490604051907f9150f8c80000000000000000000000000000000000000000000000000000000082526004820152fd5b5060ff600184015460c01c1615615b85565b602482604051907f6b9c1a9d0000000000000000000000000000000000000000000000000000000082526004820152fd5b63ffffffff1680600052606460205260406000206001600160a01b0381541615615c67576003015460501c60ff1615615c365750565b602490604051907fb0fdd2020000000000000000000000000000000000000000000000000000000082526004820152fd5b602482604051907fb842f5a70000000000000000000000000000000000000000000000000000000082526004820152fd5b6001600160a01b039182169116818110613c03570390565b6001600160a01b039182809216918291169204821181151516615cd1570290565b615cd9613064565b0290565b63ffffffff166000526064602052615d7b611132615d6a6001600160a01b039361ffff600460e08760016040600020015416604051928380927f3850c7bd0000000000000000000000000000000000000000000000000000000082525afa908115615de2575b600091615dbe575b50828781168289161115615dae57615d6291615c98565b965b16615cb0565b6001600160a01b0361271091160490565b911611615d8457565b60046040517f07a1db07000000000000000000000000000000000000000000000000000000008152fd5b90615db891615c98565b96615d64565b615dd6915060e03d811161494c5761493a818361081c565b50505050505038615d4b565b615dea613795565b615d43565b615df7613f01565b9063ffffffff91828216600052606d60205260406000209280845416911614600014615e435750600101547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b61146f9150614403565b615e55613f01565b9063ffffffff808216600052606d60205280604060002054931690831614600014615e81575060201c90565b61146f9150613c6490614022565b805160051b810160209081018183015b818110615eac5750505090565b80515481528201615e9f565b9091615ed192811015615ed5575b60051b810190613965565b9091565b615edd612dc6565b615ec6565b908092918237016000815290565b60208183031261000e5780519067ffffffffffffffff821161000e570181601f8201121561000e578051615f2381614c4b565b92615f31604051948561081c565b8184526020828401011161000e5761146f9160208085019101610aa856fea2646970667358221220a17ee6737ebff31f3432faa264c9c3e22031a16d93c7a52c8d9f83bde14583db64736f6c634300080e0033", - "deployedBytecode": "0x60806040526004361015610013575b600080fd5b60003560e01c806304a6f2641461031f5780630df181ea14610316578063134015511461030d578063136439dd146103045780631e2eaeaf146102fb5780632a90b8da146102f25780633562490c146102e957806335876476146102e05780633d0aea3d146102d75780633d56a35e146102ce5780633ffe794c146102c557806340c4f69b146102bc578063424cd833146102b357806343afafba146102aa578063569634d3146102a15780635aa6e675146102985780635c975abb1461028f5780636a486482146102865780636ae732301461027d578063706bdd25146102745780637cc2f4f51461026b5780637d2efe071461026257806383d778eb146102595780638ce25a93146102505780638f24ab11146102475780638f8022bc1461023e5780639cd1be58146102355780639dca362f1461022c578063a05c8baf14610223578063ac9650d81461021a578063b790230314610211578063c7505c1514610208578063ce4c18de146101ff578063dbc0c085146101f6578063dbd035ff146101ed578063e3d41c18146101e4578063e450f6f4146101db578063e67ed1df146101d25763fabc1cbc146101ca57600080fd5b61000e6126d4565b5061000e6125fb565b5061000e61248d565b5061000e6123f9565b5061000e612362565b5061000e6122d7565b5061000e6122af565b5061000e612115565b5061000e6120ed565b5061000e61200c565b5061000e611d8c565b5061000e611d2e565b5061000e611bf7565b5061000e611b71565b5061000e61196a565b5061000e61194b565b5061000e6116ff565b5061000e611509565b5061000e6114b0565b5061000e611472565b5061000e6113be565b5061000e6112e5565b5061000e6112c0565b5061000e611297565b5061000e611269565b5061000e611221565b5061000e611096565b5061000e610b82565b5061000e610978565b5061000e610950565b5061000e6108a4565b5061000e6106a7565b5061000e6105ee565b5061000e61056e565b5061000e61054e565b5061000e61044a565b5061000e610421565b5061000e61035c565b5061000e610333565b600091031261000e57565b503461000e57600060031936011261000e5760206001600160a01b036101a55416604051908152f35b503461000e576000602060031936011261041e5761038060ff6101705416156133fd565b61038b600435615b0a565b61039481613b30565b8173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__91823b1561041a576044604051809481937feaf393260000000000000000000000000000000000000000000000000000000083526004830152606460248301525af4801561040d575b6103fe575b50604051f35b610407906107a7565b386103f8565b610415613795565b6103f3565b5080fd5b80fd5b503461000e57600060031936011261000e5760206001600160a01b036101a45416604051908152f35b503461000e57602060031936011261000e576001600160a01b03806101a35416331415908161053e575b506105145761017061048a60ff825416156133fd565b60d7546104ea5761049f600435606654613470565b6104a6575b005b600160ff1982546104ba60ff8216156133fd565b161790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b60046040517fd2067f43000000000000000000000000000000000000000000000000000000008152fd5b60046040517fd7a2ae6a000000000000000000000000000000000000000000000000000000008152fd5b6101a25416331415905038610474565b503461000e57602060031936011261000e57602060043554604051908152f35b503461000e57600060031936011261000e576101a48054906001600160a01b0390818316803303610514576000936101a2805492806040519685167f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808989a373ffffffffffffffffffffffffffffffffffffffff19809416179055169055f35b503461000e57600060031936011261000e576101a58054906001600160a01b0390818316803303610514576000936101a3805492806040519685167f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb28989a373ffffffffffffffffffffffffffffffffffffffff19809416179055169055f35b6001600160a01b0381160361000e57565b610124359061068d8261066e565b565b60e4359061068d8261066e565b359061068d8261066e565b503461000e5760e060031936011261000e576004356106c58161066e565b61073f6024356106d48161066e565b6044356106e08161066e565b6064356106ec8161066e565b608435906106f98261066e565b60a435926107068461066e565b60c435946107138661066e565b61013d5460ff8160081c1690816000146107835750610733303b156127a8565b15978861075657612819565b61074557005b6104a461013d61ff00198154169055565b61076b61013d61010061ff0019825416179055565b61077e61013d600160ff19825416179055565b612819565b60ff6107339116156127a8565b50634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116107bb57604052565b6107c3610790565b604052565b60a0810190811067ffffffffffffffff8211176107bb57604052565b6040810190811067ffffffffffffffff8211176107bb57604052565b6060810190811067ffffffffffffffff8211176107bb57604052565b90601f601f19910116810190811067ffffffffffffffff8211176107bb57604052565b6040519061068d826107e4565b63ffffffff81160361000e57565b8015150361000e57565b60e4359061068d8261085a565b610104359061068d8261085a565b60a4359061068d8261085a565b60c4359061068d8261085a565b359061068d8261085a565b503461000e57608060031936011261000e576004356108c28161066e565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261000e576040516104a4916060820167ffffffffffffffff811183821017610943575b60405260243561091a8161066e565b82526044356109288161084c565b60208301526064356109398161085a565b6040830152612fec565b61094b610790565b61090b565b503461000e57600060031936011261000e5760206001600160a01b0360d45416604051908152f35b503461000e5761014060031936011261000e576001600160a01b038060d454163303610a4d576109d163ffffffff6004356109b28161066e565b1691826000526064602052604060002054166001600160a01b03161590565b15610a3757610a3281610a1d610a187f4182acc9c169391ef7e765eb446fc15c9d49bc73060c678bf4c424a5c0dbdbcb9463ffffffff166000526064602052604060002090565b612c59565b610a2681612e2b565b60405191829182612ec4565b0390a1005b634e487b7160e01b600052600160045260246000fd5b60046040517f85734f31000000000000000000000000000000000000000000000000000000008152fd5b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b918091926000905b828210610ac8575011610ac1575050565b6000910152565b91508060209183015181860152018291610ab0565b90601f19601f602093610afb81518092818752878088019101610aa8565b0116010190565b602080820190808352835180925260408301928160408460051b8301019501936000915b848310610b365750505050505090565b9091929394958480610b72837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a51610add565b9801930193019194939290610b26565b503461000e5760408060031936011261000e57600480359160243567ffffffffffffffff811161000e57610bb99036908401610a77565b610bc58194929461387a565b93610bda8660005260d3602052604060002090565b95610be487613b30565b60008781938295835b818110610d5f5750505050610d4f575b50610cb8575b610c19575b815180610c158582610b02565b0390f35b73__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__90813b1561000e5782517f998c53350000000000000000000000000000000000000000000000000000000081529081019485526001602086015260646040860152610c159490916000918391908290819060600103915af48015610cab575b15610c085780610c9f610ca5926107a7565b80610328565b38610c08565b610cb3613795565b610c8d565b73__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__803b1561000e576000845180927f651524ed0000000000000000000000000000000000000000000000000000000082528180610d198b8983016020606491939293604081019481520152565b03915af48015610d42575b610d2f575b50610c03565b80610c9f610d3c926107a7565b38610d29565b610d4a613795565b610d24565b610d5890615b0a565b5038610bfd565b9091929693610d77610d728385876138c3565b61393a565b610d8081613928565b610dd8575080610dc0610daf610da7610d9d610dc59587896138c3565b6020810190613965565b810190613b11565b906001978015610dce575b9a614a64565b613460565b908a9291610bed565b5060008212610dba565b939650610de9610d728284866138c3565b93610df385613928565b6001948503610e425750610e16610e0e610d9d8385876138c3565b810190613b02565b93610e21858d614e4f565b6000819512610e35575b50610dc590613460565b9650869550610dc5610e2b565b6002610e55610d728486889c969c6138c3565b610e5e81613928565b03610edf575050610eb1610ebf610e768884866138c3565b610e9a8d610e94610e8c60209485810190613965565b810190613a7c565b91615162565b8c5192830191825260208201529092839160400190565b03601f19810183528261081c565b610ec9878b613a02565b52610ed4868a613a02565b50610dc58396613460565b6003610eef610d728a86886138c3565b610ef881613928565b03610f34575050610eb1610ebf610f108884866138c3565b610e9a8d610f2e610f2660209485810190613965565b810190613a57565b91614f36565b93509587610f46610d728385876138c3565b610f4f81613928565b03610f815780610f7b610f74610f6c610d9d610dc59587896138c3565b810190613a24565b91896156cf565b50613460565b6005610f91610d728385876138c3565b610f9a81613928565b03610fd05780610f7b610fcb610fc2610fba610d9d610dc596888a6138c3565b81019061145a565b63ffffffff1690565b6153b9565b6006610fe0610d728385876138c3565b610fe981613928565b036110505780610ffd610dc59284866138c3565b61103b61102963ffffffff61102261101a60209586810190613965565b8101906139b6565b911661559e565b8c519283019081528290602001610eb1565b611045828d613a02565b52610f7b818c613a02565b611063610d72611092928a948c966138c3565b92519283927f62c9ca420000000000000000000000000000000000000000000000000000000084528301613947565b0390fd5b503461000e5760208060031936011261000e5760665460d85460049283358215611218575b600090806111f55750508293915b8481106110e65750505081036110e15750600060d855005b60d855005b8060008361113e611132600261112463ffffffff61110661118799612ddd565b90549060031b1c1663ffffffff166000526064602052604060002090565b01546001600160a01b031690565b6001600160a01b031690565b86604051809481937f5e622abc0000000000000000000000000000000000000000000000000000000083525af19081156111e8575b6000916111bb575b508061118c5750613460565b6110c9565b6111b5906111a26067546001600160a01b031690565b6001600160a01b036101a3541690614b6b565b38610f7b565b6111db9150843d86116111e1575b6111d3818361081c565b810190613ef2565b3861117b565b503d6111c9565b6111f0613795565b611173565b6111ff9084613448565b905083811015611211575b93916110c9565b508261120a565b600092506110bb565b503461000e57604060031936011261000e5760206112616024356004356112478261084c565b8060005260d3845261125c6040600020613b30565b61559e565b604051908152f35b503461000e57602060031936011261000e576104a46004358060005260d3602052610fcb6040600020613b30565b503461000e57600060031936011261000e5760206001600160a01b036101a25416604051908152f35b503461000e57600060031936011261000e57602060ff61017054166040519015158152f35b503461000e57604060031936011261000e57610c156024356113068161084c565b60043560005260d360205263ffffffff604060002091604051927f7188a1ed00000000000000000000000000000000000000000000000000000000845260048401521660248201526064604482015260208160648173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af49081156113b1575b600091611393575b506040519081529081906020820190565b6113ab915060203d81116111e1576111d3818361081c565b38611382565b6113b9613795565b61137a565b503461000e57602060031936011261000e576004356113dc8161066e565b6001600160a01b03806101a354163314158061144b575b610514576000916101a59073ffffffffffffffffffffffffffffffffffffffff19838354921691826040519582167f9b068aae3039a2512c2f13bffb5fd9d95b1895b276b5c7ddf1d4fa24ec3686588888a316179055f35b5033816101a2541614156113f3565b9081602091031261000e573561146f8161084c565b90565b503461000e57602060031936011261000e5760206112616004356114958161084c565b615def565b8060020b0361000e57565b359061068d8261149a565b503461000e57608060031936011261000e576104a46004356024356114d48161084c565b604435906114e18261149a565b606435926114ee8461149a565b8060005260d36020526115046040600020613b30565b6156cf565b503461000e57606060031936011261000e576024356115278161084c565b6044356101709061153c60ff835416156133fd565b611547600435615b0a565b9161155183613b30565b60009361156560ff868512935416156133fd565b846115708383615b55565b9473__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__803b15611678576040517ff5a284a1000000000000000000000000000000000000000000000000000000008152600481019290925263ffffffff93909316602482015260448101859052606480820152831515608482015291829060a49082905af4801561166b575b611658575b5083821315611620575061161261161b92546001600160a01b031690565b30903390614bdd565b604051f35b61162c575b5050604051f35b61164961164361165193546001600160a01b031690565b91614508565b903390614b6b565b3880611625565b80610c9f611665926107a7565b386115f4565b611673613795565b6115ef565b8280fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc60a091011261000e57604051906116b3826107c8565b8160443581526064356116c58161066e565b60208201526084356116d68161085a565b604082015260a4356116e78161085a565b6060820152608060c435916116fb8361085a565b0152565b503461000e5760e060031936011261000e5760243561171d8161084c565b6117263661167c565b809161017061173960ff825416156133fd565b61175b60ff611749600435615b0a565b9261175384613b30565b5416156133fd565b61176482615c00565b604091829161179f835195869384937f140cf61e00000000000000000000000000000000000000000000000000000000855260048501615352565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af492831561193e575b6000928394611909575b506117d484614543565b606c5481106118d757506001600160a01b036117fa60208301516001600160a01b031690565b161515806118c1575b61181a575b50519081526020810191909152604090f35b818101906118288251151590565b91826118a5575b821561186c575b5050156118435738611808565b600490517f07a1db07000000000000000000000000000000000000000000000000000000008152fd5b519091501561187a565b1590565b9081611889575b503880611836565b905061189e61189784614543565b9151614543565b1438611881565b91506118b085614543565b6118ba8251614543565b149161182f565b506118d26118766060830151151590565b611803565b82517f256d6b9a0000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b9093508161192d9293503d8411611937575b611925818361081c565b81019061533c565b91909192386117ca565b503d61191b565b611946613795565b6117c0565b503461000e57600060031936011261000e57602060d254604051908152f35b503461000e5761010060031936011261000e57600480359061198b8261084c565b60e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261000e576001600160a01b036101a254163303611b49576119ed60036119e78463ffffffff166000526064602052604060002090565b01612a7b565b611a086119fb611132612a62565b6001600160a01b03161590565b611b2b5763ffffffff61012c81611a1d612a3d565b1610908115611b15575b50611af65761ffff6127108082611a3c612a0f565b1611611ad857611a54611a4d612a1b565b61ffff1690565b11611aba576107d090611a65612a27565b1611611a9b576040517f4182acc9c169391ef7e765eb446fc15c9d49bc73060c678bf4c424a5c0dbdbcb9080610a328582612f68565b604051636a098dd160e11b815260249181019182529081906020010390fd5b604051636a098dd160e11b8152602381840190815281906020010390fd5b604051636a098dd160e11b8152602281850190815281906020010390fd5b604051636a098dd160e11b815260219181019182529081906020010390fd5b620151809150611b23612a3d565b161138611a27565b604051636a098dd160e11b8152602091810182815290918291010390fd5b6040517fd7a2ae6a000000000000000000000000000000000000000000000000000000008152fd5b503461000e57602060031936011261000e57600435611b8f8161066e565b6001600160a01b03806101a254163303610514576000916101a49073ffffffffffffffffffffffffffffffffffffffff19838354921691826040519582167f8c405decc72a19ef328c92989ce6db4e4a498e1c246413fd60997a3051ba5cff8888a316179055f35b503461000e57604060031936011261000e57602435610170611c1d60ff825416156133fd565b611c2d60ff611749600435615b0a565b8115611d045773__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__803b1561000e576040517fd25c4a6f000000000000000000000000000000000000000000000000000000008152600481019290925260248201839052606460448301819052600190830152600090829060849082905af48015611cf7575b611ce4575b506000811315611ccb576104a4906116126067546001600160a01b031690565b6104a4906116496116436067546001600160a01b031690565b80610c9f611cf1926107a7565b38611cab565b611cff613795565b611ca6565b60046040517f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b503461000e57600060031936011261000e5760206112616136c0565b60031961010091011261000e57600490565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc61010091011261000e57604490565b503461000e5761016060031936011261000e57611da836611d4a565b610104356101243591610144356001600160a01b036101a254163303610514576127109361ffff8581611dda86612a33565b1611611ff35785611df0611a4d60208701612a33565b11611fda5760409580611e07611a4d898801612a33565b11611fc25780611e1c611a4d60608801612a33565b11611faa57611e30611a4d60808701612a33565b11611f92576103e890611e4560a08601612a33565b1611611f7a57633b9aca008067ffffffffffffffff611e6660c087016130a4565b1611611f625780611e89611e7c60e087016130a4565b67ffffffffffffffff1690565b11611f4a57808511611f3257808211611f1a578211611f025791611efc60009594927f697aec6e94e319190380ab0f1f10018d81b64da2479eb874be92c9a733e0a83794611ed6846130ae565b611edf85606b55565b611ee881606c55565b611ef182606a55565b865194859485613311565b0390a151f35b8451636a098dd160e11b8152603a6004820152602490fd5b8551636a098dd160e11b815260396004820152602490fd5b8551636a098dd160e11b815260386004820152602490fd5b8551636a098dd160e11b815260376004820152602490fd5b8551636a098dd160e11b815260366004820152602490fd5b8451636a098dd160e11b815260356004820152602490fd5b8551636a098dd160e11b815260346004820152602490fd5b8651636a098dd160e11b815260336004820152602490fd5b8651636a098dd160e11b815260326004820152602490fd5b604051636a098dd160e11b815260316004820152602490fd5b604051636a098dd160e11b815260306004820152602490fd5b50602060031936011261000e576004803567ffffffffffffffff811161000e576120399036908301610a77565b906120438261387a565b9160005b81811061205c5760405180610c158682610b02565b60008061206a838587615eb8565b6040939161207c855180938193615ee2565b0390305af49061208a614dce565b918290156120b3575050906120ae916120a38287613a02565b52610f7b8186613a02565b612047565b826044899394511061000e5761109291836120d8920160248091518301019101615ef0565b925192839262461bcd60e51b84528301614dfe565b503461000e57600060031936011261000e5760206001600160a01b0360d55416604051908152f35b503461000e5761014060031936011261000e576024356121348161084c565b606061213f36611d5c565b916101709261215260ff855416156133fd565b61217f60ff612176612165600435615b0a565b9361216f85613b30565b36906137bd565b955416156133fd565b61218882615c00565b828401516001600160a01b03168061228f575b506121d360405194859384937fc27789d100000000000000000000000000000000000000000000000000000000855260048501615050565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af48015612282575b6000908192829161224e575b50606c54811061221b5750604080519182526020820192909252f35b6040517f256d6b9a0000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b915050612272915060603d811161227b575b61226a818361081c565b810190615028565b919091386121ff565b503d612260565b61228a613795565b6121f3565b6122a9906122a2608087015161ffff1690565b9084615cdd565b3861219b565b503461000e57602060031936011261000e5760206112616004356122d28161084c565b615e4d565b503461000e57600060031936011261000e5760206001600160a01b036101a35416604051908152f35b60209067ffffffffffffffff811161231a575b60051b0190565b612322610790565b612313565b6020908160408183019282815285518094520193019160005b82811061234e575050505090565b835185529381019392810192600101612340565b503461000e5760208060031936011261000e5760043567ffffffffffffffff811161000e573660238201121561000e578060040135906123a182612300565b916123af604051938461081c565b80835260248484019160051b8301019136831161000e57602401905b8282106123ea57610c156123de85615e8f565b60405191829182612327565b813581529084019084016123cb565b503461000e57602060031936011261000e5760043560005260d3602052610c156040600020604051907fc4b22b8600000000000000000000000000000000000000000000000000000000825260048201526064602482015260208160448173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af49081156113b15760009161139357506040519081529081906020820190565b503461000e57604060031936011261000e576004356124ab8161084c565b602435906124b76136c0565b90610170926124ca60ff855416156133fd565b6124d383615b0a565b936124dd85613b30565b6124ef60ff60008412925416156133fd565b6124f98184615b55565b9273__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__90813b1561000e576040517ff5a284a1000000000000000000000000000000000000000000000000000000008152600481019790975263ffffffff166024870152604486018390526064808701528115156084870152610c159590600090829060a49082905af480156125ee575b6125db575b5060008213156125b157506116126125a192546001600160a01b031690565b6040519081529081906020820190565b6125bd575b50506125a1565b6116496116436125d493546001600160a01b031690565b38806125b6565b80610c9f6125e8926107a7565b38612582565b6125f6613795565b61257d565b503461000e5760408060031936011261000e5760243561261a8161085a565b60043560005260d360205281600020908251917f0c6d7f3400000000000000000000000000000000000000000000000000000000835260048301521515602482015260646044820152818160648173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af49182156126c7575b60009182936126a25750519081526020810191909152604090f35b816126bf929450610c1593503d851161193757611925818361081c565b929091611808565b6126cf613795565b612687565b503461000e57602060031936011261000e576001600160a01b03806101a354163314159081612798575b506105145761017061271360ff825416613675565b60d65461276e5761272860043560665461358a565b61272e57005b60ff19815461273f60ff8216613675565b1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b60046040517ffc23b9cd000000000000000000000000000000000000000000000000000000008152fd5b6101a254163314159050386126fe565b156127af57565b608460405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b93916128b87f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb2936000958694986001600160a01b039a8b80928173ffffffffffffffffffffffffffffffffffffffff199c168c60d454161760d4558185168c6067541617606755168a60d554161760d5551688606854161760685589604051926128a284610800565b168252603c602083015260016040830152615942565b61013d9680885460ff8160081c169081861461297057506128da303b156127a8565b159788612943575b16916101a2838882541617905560405192847f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808186a31694856101a391825416179055a3612934575b5061068d61297d565b61ff001981541690553861292b565b61295861013d61010061ff0019825416179055565b61296b61013d600160ff19825416179055565b6128e2565b60ff6128da9116156127a8565b60ff61013d5460081c16156129995761017060ff198154169055565b608460405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152fd5b61ffff81160361000e57565b60243561146f81612a03565b60443561146f81612a03565b60643561146f81612a03565b3561146f81612a03565b60843561146f8161084c565b60e43561146f8161085a565b6101043561146f8161085a565b60e43561146f8161066e565b6101243561146f8161066e565b61068d90612abd602435612a8e81612a03565b829061ffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000825416179055565b612b01604435612acc81612a03565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff1660109190911b63ffff000016178255565b612b47606435612b1081612a03565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff1660209190911b65ffff0000000016178255565b608435612b538161084c565b7fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff69ffffffff00000000000083549260301b169116178155612bd660a435612b9a8161085a565b82547fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff1690151560501b6aff0000000000000000000016178255565b612c2260c435612be58161085a565b82547fffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffff1690151560581b6bff000000000000000000000016178255565b60e43590612c2f8261066e565b906bffffffffffffffffffffffff6bffffffffffffffffffffffff1983549260601b169116179055565b600361068d91612c97600435612c6e8161066e565b82906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b612cd2602435612ca68161066e565b60018301906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b612d0d604435612ce18161066e565b60028301906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b01612d1d606435612a8e81612a03565b612d2c608435612acc81612a03565b612d3b60a435612b1081612a03565b60c435612d478161084c565b7fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff69ffffffff00000000000083549260301b169116178155612d8a612b9a612a49565b612d95612be5612a55565b612d9d612a6e565b6bffffffffffffffffffffffff6bffffffffffffffffffffffff1983549260601b169116179055565b50634e487b7160e01b600052603260045260246000fd5b90606654821015612e1e575b6066600052601c8260031c7f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354019260021b1690565b612e26612dc6565b612de9565b6066549068010000000000000000821015612eac575b6001820180606655821015612e9f575b60666000528160031c7f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354019160e083549160051b169163ffffffff9283811b93849216901b16911916179055565b612ea7612dc6565b612e51565b612eb4610790565b612e41565b359061068d82612a03565b63ffffffff91821681526101008101929161068d9190606435612ee681612a03565b61ffff809116602084015280608435612efe81612a03565b16604084015260a435612f1081612a03565b16606083015260c435612f228161084c565b166080820152612f3c612f33610864565b151560a0830152565b612f50612f47610871565b151560c0830152565b60e0612f5a61067f565b6001600160a01b0316910152565b63ffffffff91821681526101008101929161068d9190602435612f8a81612a03565b61ffff809116602084015280604435612fa281612a03565b166040840152606435612fb481612a03565b166060830152608435612fc68161084c565b166080820152612fd7612f3361087f565b612fe2612f4761088c565b60e0612f5a61068f565b906001600160a01b03806101a254163303610514578151161561304b576201518063ffffffff613023602084015163ffffffff1690565b16116130325761068d91615942565b604051636a098dd160e11b815260116004820152602490fd5b604051636a098dd160e11b815260106004820152602490fd5b50634e487b7160e01b600052601160045260246000fd5b50634e487b7160e01b600052601260045260246000fd5b67ffffffffffffffff81160361000e57565b3561146f81613092565b6132b860e061068d9261ffff81356130c581612a03565b167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00006069541617606955613136602082013561310081612a03565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff63ffff00006069549260101b16911617606955565b61317f604082013561314781612a03565b7fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff65ffff000000006069549260201b16911617606955565b606081013561318d81612a03565b7fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff67ffff0000000000006069549260301b169116176069556132106131d460808301612a33565b7fffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff69ffff00000000000000006069549260401b16911617606955565b61325d61321f60a08301612a33565b7fffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffff6bffff000000000000000000006069549260501b16911617606955565b6132b261326c60c083016130a4565b7fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff73ffffffffffffffff0000000000000000000000006069549260601b16911617606955565b016130a4565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff00000000000000000000000000000000000000006069549260a01b16911617606955565b359061068d82613092565b90949392610140926133ed6133dc60e0610160860199803561333281612a03565b61ffff8091168852602082013561334881612a03565b16602088015261336861335d60408301612eb9565b61ffff166040890152565b61338261337760608301612eb9565b61ffff166060890152565b61339c61339160808301612eb9565b61ffff166080890152565b6133b66133ab60a08301612eb9565b61ffff1660a0890152565b6133d66133c560c08301613306565b67ffffffffffffffff1660c0890152565b01613306565b67ffffffffffffffff1660e0850152565b6101008301526101208201520152565b1561340457565b606460405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152fd5b81198111613454570190565b61345c613064565b0190565b6001906000198114613454570190565b60d65492918315613581575b6000908061355f57505080925b8381106134a7575082149182156134a25750600060d655565b60d655565b63ffffffff6134b582612ddd565b90549060031b1c1660005260646020526040906134e3611132600284600020016001600160a01b0390541690565b803b1561000e576000613540935180927f5124033600000000000000000000000000000000000000000000000000000000825281838161352b60048201906000602083019252565b03925af18015613552575b6135455750613460565b613489565b80610c9f6111b5926107a7565b61355a613795565b613536565b6135699085613448565b90508181101561357a575b92613489565b5080613574565b6000935061347c565b60d7549291831561366c575b6000908061364a57505080925b8381106135c1575082149182156135bc5750600060d755565b60d755565b63ffffffff6135cf82612ddd565b90549060031b1c1660005260646020526040906001600160a01b03600283600020015416803b1561000e576000809160246136459551809481937f51240336000000000000000000000000000000000000000000000000000000008352600160048401525af18015613552576135455750613460565b6135a3565b6136549085613448565b905081811015613665575b926135a3565b508061365f565b60009350613596565b1561367c57565b606460405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152fd5b6136d060ff6101705416156133fd565b60d2547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8111613788575b6001810160d255600081815260d36020526040902080546bffffffffffffffffffffffff163360601b6bffffffffffffffffffffffff19161781556bffffffffffffffffffffffff82166bffffffffffffffffffffffff198254161790556040518181527f7325fb14450d3e5eb288c620b4ff1d6b43a41b33b4a4f143ae88cd4c12f99ea360203392a290565b613790613064565b6136fb565b506040513d6000823e3d90fd5b359081600f0b820361000e57565b3590600382101561000e57565b809291610100918291031261000e5760405190810181811067ffffffffffffffff82111761386d575b60405260e06138688183956137fa816114a5565b8552613808602082016114a5565b6020860152613819604082016137a2565b604086015261382a6060820161069c565b606086015261383b60808201612eb9565b608086015261384c60a08201610899565b60a086015261385d60c082016137b0565b60c086015201610899565b910152565b613875610790565b6137e6565b9061388482612300565b613891604051918261081c565b828152601f196138a18294612300565b019060005b8281106138b257505050565b8060606020809385010152016138a6565b9190811015613904575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561000e570190565b61390c612dc6565b6138cd565b50634e487b7160e01b600052602160045260246000fd5b6007111561393257565b61068d613911565b35600781101561000e5790565b91906020830192600782101561395a5752565b613962613911565b52565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e5760200191813603831361000e57565b919082604091031261000e57602082356139cf8161084c565b92013561146f8161084c565b6020908051156139e9570190565b61345c612dc6565b6040908051600110156139e9570190565b6020918151811015613a17575b60051b010190565b613a1f612dc6565b613a0f565b9081606091031261000e578035613a3a8161084c565b9160406020830135613a4b8161149a565b92013561146f8161149a565b91906101208382031261000e5761146f9060208435613a758161084c565b94016137bd565b809291039160c0831261000e5760a0601f198235613a998161084c565b94011261000e5760a060405191613aaf836107c8565b602081013583526040810135613ac48161066e565b60208401526060810135613ad78161085a565b60408401526080810135613aea8161085a565b60608401520135613afa8161085a565b608082015290565b9081602091031261000e573590565b919082604091031261000e5760208235613b2a8161084c565b92013590565b60005b60088060ff83161015613b9257811015613b97575b63ffffffff60018260031c8401015460e08360051b161c16908115613b9257613b72600192613c1c565b60ff809116908114613b85575b01613b33565b613b8d613064565b613b7f565b505050565b613b9f612dc6565b613b48565b60008212827f8000000000000000000000000000000000000000000000000000000000000000018212811516613c0f575b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01821316613c03570390565b613c0b613064565b0390565b613c17613064565b613bd5565b613c24613f01565b613c3e8263ffffffff16600052606d602052604060002090565b805463ffffffff838116911614613b9257613c5883614403565b613c69613c6485614022565b613fad565b937c010000000000000000000000000000000000000000000000000000000080831090811591613e35575b50613e2e5761068d94613d49613d4e613dcf94613cd56003613cc9613d9a9763ffffffff166000526064602052604060002090565b015460201c61ffff1690565b613cf561ffff613ced613ce88886613ba4565b614543565b921683613e40565b1015613dff57613d49600188017c01000000000000000000000000000000000000000000000000000000007fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff825416179055565b614492565b60018601907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000825416179055565b825463ffffffff1660209190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016178255565b9063ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055565b613d49600188017fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8154169055565b5050505050565b905085101538613c94565b9060001981830981830291828083109203918083039214613e9d57612710908282111561000e577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b505061271091500490565b6000198282099082810292838084109303928084039314613ee95768010000000000000000918383111561000e570990828211900360c01b910360401c1790565b50505060401c90565b9081602091031261000e575190565b61a4b146148015613fa1575b8015613f95575b15613f8b5763ffffffff6040517fa3b1b31d00000000000000000000000000000000000000000000000000000000815260208160048160645afa908115613f7e575b600091613f6257501690565b613f7a915060203d81116111e1576111d3818361081c565b1690565b613f86613795565b613f56565b63ffffffff431690565b5062066eec4614613f14565b5062066eeb4614613f0d565b6001600160a01b03166401000276a381108015614004575b613fd3578061146f91613ea8565b602490604051907f5d236c450000000000000000000000000000000000000000000000000000000082526004820152fd5b5073fffd8963efd1fc6a506488495d951d5263988d26811015613fc5565b61403c9063ffffffff166000526064602052604060002090565b60036140666001600160a01b0392836001820154169063ffffffff938491015460301c169061484c565b60020b9060008212156143fd5781600003915b620d89e883116143d35760018316156143aa5770ffffffffffffffffffffffffffffffffff6ffffcb933bd6fad37aa2d162d1a5940015b16926002811661438e575b60048116614372575b60088116614356575b6010811661433a575b6020811661431e575b60408116614302575b6080908181166142e7575b61010081166142cc575b61020081166142b1575b6104008116614296575b610800811661427b575b6110008116614260575b6120008116614245575b614000811661422a575b618000811661420f575b6201000081166141f4575b6202000081166141da575b6204000081166141c0575b62080000166141a5575b50600012614195575b811661418c5760ff60005b169060201c011690565b60ff6001614182565b9061419f90614558565b90614177565b6b048a170391f7dc42444e8fa26000929402901c929061416e565b6d2216e584f5fa1ea926041bedfe98909402811c93614164565b936e5d6af8dedb81196699c329225ee60402811c93614159565b936f09aa508b5b7a84e1c677de54f3e99bc902811c9361414e565b936f31be135f97d08fd981231505542fcfa602811c93614143565b936f70d869a156d2a1b890bb3df62baf32f702811c93614139565b936fa9f746462d870fdf8a65dc1f90e061e502811c9361412f565b936fd097f3bdfd2022b8845ad8f792aa582502811c93614125565b936fe7159475a2c29b7443b29c7fa6e889d902811c9361411b565b936ff3392b0822b70005940c7a398e4b70f302811c93614111565b936ff987a7253ac413176f2b074cf7815e5402811c93614107565b936ffcbe86c7900a88aedcffc83b479aa3a402811c936140fd565b936ffe5dee046a99a2a811c461f1969c305302811c936140f3565b926fff2ea16466c96a3843ec78b326b528610260801c926140e8565b926fff973b41fa98c081472e6896dfb254c00260801c926140df565b926fffcb9843d60f6159c9db58835c9266440260801c926140d6565b926fffe5caca7e10e4e61c3624eaa0941cd00260801c926140cd565b926ffff2e50f5f656932ef12357cf3c7fdcc0260801c926140c4565b926ffff97272373d413259a46990580e213a0260801c926140bb565b70ffffffffffffffffffffffffffffffffff7001000000000000000000000000000000006140b0565b60046040517f2bc80f3a000000000000000000000000000000000000000000000000000000008152fd5b81614079565b63ffffffff80911660005260646020526020600360406000200154916024604051809481937fdd86c1010000000000000000000000000000000000000000000000000000000083528160301c16600483015260601c5afa908115614485575b60009161446d575090565b61146f915060203d81116111e1576111d3818361081c565b61448d613795565b614462565b7c010000000000000000000000000000000000000000000000000000000081116144d7577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b602490604051907f1ba344530000000000000000000000000000000000000000000000000000000082526004820152fd5b7f80000000000000000000000000000000000000000000000000000000000000008114614536575b60000390565b61453e613064565b614530565b600081131561454f5790565b61146f90614508565b8015614566575b6000190490565b61456e61307b565b61455f565b6040519061458082610800565b600282526040366020840137565b81601f8201121561000e578051916145a583612300565b926145b3604051948561081c565b808452602092838086019260051b82010192831161000e578301905b8282106145dd575050505090565b83809183516145eb8161066e565b8152019101906145cf565b91909160408184031261000e5780519267ffffffffffffffff9384811161000e5782019381601f8601121561000e5784519461463186612300565b9061463f604051928361081c565b868252602096878084019160051b8301019185831161000e578801905b82821061467b575050509483015190811161000e5761146f920161458e565b81518060060b810361000e57815290880190880161465c565b6020908160408183019282815285518094520193019160005b8281106146bb575050505090565b835163ffffffff16855293810193928101926001016146ad565b60060b9060060b9060008212827fffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000018212811516614723575b82667fffffffffffff01821316613c03570390565b61472b613064565b61470e565b60060b9060060b90811561477c575b60001982147fffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000821416614770570590565b614778613064565b0590565b61478461307b565b61473f565b9060060b90811561479c575b60060b0790565b6147a461307b565b614795565b6000199060020b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000008114613454570190565b908160e091031261000e5780516147f18161066e565b9160208201516148008161149a565b91604081015161480f81612a03565b91606082015161481e81612a03565b91608081015161482d81612a03565b9160a082015160ff8116810361000e5760c09092015161146f8161085a565b9063ffffffff81168015614a04576148cb6001600160a01b0393614886614871614573565b9461487b866139db565b9063ffffffff169052565b600094859182614895876139f1565b521693604051809381927f883bdbfd00000000000000000000000000000000000000000000000000000000835260048301614694565b0381865afa8491816149df575b5061496057505060e0600491604051928380927f3850c7bd0000000000000000000000000000000000000000000000000000000082525afa918215614953575b91614921575090565b614942915060e03d811161494c575b61493a818361081c565b8101906147db565b5050505050905090565b503d614930565b61495b613795565b614918565b61498b91925061498561497861497f614978846139f1565b5160060b90565b926139db565b906146d5565b9060060b6149a261499c8284614730565b60020b90565b928260060b1291826149c1575b50506149b85790565b61146f906147a9565b6149d69250906149d091614789565b60060b90565b151538806149af565b6149fc9192503d8087833e6149f4818361081c565b8101906145f6565b5090386148d8565b505061146f9060e06001600160a01b03916004604051809481937f3850c7bd000000000000000000000000000000000000000000000000000000008352165afa908115614a57575b600091614921575090565b614a5f613795565b614a4c565b919091614a7760ff6101705416156133fd565b6000821290614a868285615b55565b9373__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__91823b1561000e576040517ff5a284a1000000000000000000000000000000000000000000000000000000008152600481019190915263ffffffff919091166024820152604481018490526064808201526000608482018190529091829060a49082905af48015614b5e575b614b4b575b506000821315614b2c575061161261068d92546001600160a01b031690565b614b34575050565b61164961164361068d93546001600160a01b031690565b80610c9f614b58926107a7565b38614b0d565b614b66613795565b614b08565b61068d926001600160a01b03604051937fa9059cbb0000000000000000000000000000000000000000000000000000000060208601521660248401526044830152604482526080820182811067ffffffffffffffff821117614bd0575b604052614cfc565b614bd8610790565b614bc8565b909261068d93604051937f23b872dd0000000000000000000000000000000000000000000000000000000060208601526001600160a01b03809216602486015216604484015260648301526064825260a0820182811067ffffffffffffffff821117614bd057604052614cfc565b601f19601f60209267ffffffffffffffff8111614c69575b01160190565b614c71610790565b614c63565b9081602091031261000e575161146f8161085a565b15614c9257565b608460405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6001600160a01b03169060405190614d13826107e4565b6020928383527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656484840152803b15614d8a5760008281928287614d659796519301915af1614d5f614dce565b90614e0f565b80519081614d7257505050565b8261068d93614d85938301019101614c76565b614c8b565b6064846040519062461bcd60e51b82526004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b3d15614df9573d90614ddf82614c4b565b91614ded604051938461081c565b82523d6000602084013e565b606090565b90602061146f928181520190610add565b90919015614e1b575090565b815115614e2b5750805190602001fd5b6110929060405191829162461bcd60e51b8352602060048401526024830190610add565b614e5f60ff6101705416156133fd565b8115611d045773__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__803b1561000e576040517fd25c4a6f000000000000000000000000000000000000000000000000000000008152600481019290925260248201839052606460448301819052600090830181905290829060849082905af48015614f29575b614f16575b506000811315614efd5761068d906116126067546001600160a01b031690565b61068d906116496116436067546001600160a01b031690565b80610c9f614f23926107a7565b38614edd565b614f31613795565b614ed8565b90606091939293614f4d60ff6101705416156133fd565b614f5682615c00565b828501516001600160a01b03168061500f575b50614fa160405195869384937fc27789d1000000000000000000000000000000000000000000000000000000008552600485016150f7565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af48015615002575b60009081938291614fdc575b50606c54811061221b57509190565b915050614ff891925060603d811161227b5761226a818361081c565b9291909238614fcd565b61500a613795565b614fc1565b615022906122a2608088015161ffff1690565b38614f69565b9081606091031261000e578051916040602083015192015190565b90600382101561395a5752565b6150e860e061016093969563ffffffff61068d966101808601998652166020850152805160020b6040850152602081015160020b60608501526040810151600f0b60808501526150b0606082015160a08601906001600160a01b03169052565b608081015161ffff1660c085015260a08101511515848301526150dc60c0820151610100860190615043565b01511515610120830152565b60646101408201520160019052565b61515660e061016093969563ffffffff6000966101808601998652166020850152805160020b6040850152602081015160020b60608501526040810151600f0b60808501526150b0606082015160a08601906001600160a01b03169052565b60646101408201520152565b908293929161517760ff6101705416156133fd565b61518082615c00565b6040918291615219835195869384937f140cf61e00000000000000000000000000000000000000000000000000000000855260048501608061010092959463ffffffff6000956101208501988552166020840152805160408401526001600160a01b03602082015116606084015260408101511515828401526060810151151560a08401520151151560c0820152606460e08201520152565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af493841561532f575b600092839561530a575b5061524e85614543565b606c5481106118d757506001600160a01b0361527460208301516001600160a01b031690565b161515806152f4575b615288575b50509190565b818101906152968251151590565b91826152d8575b82156152b1575b5050156118435780615282565b51159150816152c3575b5038806152a4565b90506152d161189784614543565b14386152bb565b91506152e386614543565b6152ed8251614543565b149161529d565b506153056118766060830151151590565b61527d565b909450816153259293503d841161193757611925818361081c565b9190919338615244565b615337613795565b61523a565b919082604091031261000e576020825192015190565b608061010092959463ffffffff61068d956101208501988552166020840152805160408401526001600160a01b03602082015116606084015260408101511515828401526060810151151560a08401520151151560c0820152606460e08201520160019052565b6153c960ff6101705416156133fd565b61542360606153e28360005260d3602052604060002090565b604051809381927fdf19bf09000000000000000000000000000000000000000000000000000000008352600483016020606491939293604081019481520152565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af4918215615525575b600092839284916154ff575b5061545b8385615532565b9260008513156154cd57907f688f0846fe2852572c467d5e769db101b0fea55e8849406d85c9fb322b95299b916154a58661549e6067546001600160a01b031690565b3390614b6b565b6154ae816157bf565b604080519586526020860187905285015260608401523392608090a390565b6040517fef37dcc700000000000000000000000000000000000000000000000000000000815260048101869052602490fd5b9193505061551b915060603d811161227b5761226a818361081c565b9192909138615450565b61552d613795565b615444565b60008112817f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038313811516615591575b817f800000000000000000000000000000000000000000000000000000000000000003831216613454570190565b615599613064565b615563565b61561d916155c86040926155b860ff6101705416156133fd565b60005260d3602052604060002090565b6155d182615c00565b825193849283927fec1464960000000000000000000000000000000000000000000000000000000084526004840160409063ffffffff6064939594606083019683521660208201520152565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af480156156c2575b60009182916156a2575b5060008213156156705761146f9061566b8361549e6067546001600160a01b031690565b6157bf565b6040517fef37dcc700000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b90506156bc915060403d811161193757611925818361081c565b38615647565b6156ca613795565b61563d565b929091926156e360ff6101705416156133fd565b60005260d36020526040600020916156fa81615c00565b606b549373__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__93843b1561000e5763ffffffff9460009460c49360405197889687957fe0448f0a000000000000000000000000000000000000000000000000000000008752600487015216602485015260020b604484015260020b6064830152866084830152606460a48301525af480156157b2575b61579f575b5061146f8161549e6067546001600160a01b031690565b80610c9f6157ac926107a7565b38615788565b6157ba613795565b615783565b60008113156157e45761068d906001600160a01b0380606754169060d5541690614b6b565b6157f96001600160a01b0360d5541691614508565b813b1561000e576000916024839260405194859384927f379607f500000000000000000000000000000000000000000000000000000000845260048401525af18015615850575b6158475750565b61068d906107a7565b615858613795565b615840565b6158ce602060016001600160a01b039361589d8587511682906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b019301519182511683906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b6020810151907fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff77ffffffff000000000000000000000000000000000000000078ff00000000000000000000000000000000000000000000000060408654940151151560c01b169360a01b16911617179055565b919063ffffffff83166001600160a01b03841615615ad85761598a6118766119fb61597d8463ffffffff166000526065602052604060002090565b546001600160a01b031690565b80615a9d575b615a3d57926159f47f52983c04d8ccd4808cd0fcb24e6e48106ecb41e803d6270c6c94a15e3ebd08d293946159ef6159c661083f565b6001600160a01b03851681529185602084015263ffffffff166000526065602052604060002090565b61585d565b615a3860405192839283909291604060609160808401956001600160a01b038091168552815116602085015263ffffffff6020820151168285015201511515910152565b0390a1565b615a5b61597d859263ffffffff166000526065602052604060002090565b6040517fa5d4d0b50000000000000000000000000000000000000000000000000000000081526001600160a01b03928316600482015291166024820152604490fd5b50615ad361187685615ac261597d8563ffffffff166000526065602052604060002090565b6001600160a01b0390811691161490565b615990565b6040517f76d8a93100000000000000000000000000000000000000000000000000000000815260006004820152602490fd5b60005260d3602052604060002090815460601c3303615b2557565b60246040517f0504a20d000000000000000000000000000000000000000000000000000000008152336004820152fd5b63ffffffff90929192168060005260656020526040600020926001600160a01b0384541615615bcf571580615bbd575b615b8c5750565b602490604051907f9150f8c80000000000000000000000000000000000000000000000000000000082526004820152fd5b5060ff600184015460c01c1615615b85565b602482604051907f6b9c1a9d0000000000000000000000000000000000000000000000000000000082526004820152fd5b63ffffffff1680600052606460205260406000206001600160a01b0381541615615c67576003015460501c60ff1615615c365750565b602490604051907fb0fdd2020000000000000000000000000000000000000000000000000000000082526004820152fd5b602482604051907fb842f5a70000000000000000000000000000000000000000000000000000000082526004820152fd5b6001600160a01b039182169116818110613c03570390565b6001600160a01b039182809216918291169204821181151516615cd1570290565b615cd9613064565b0290565b63ffffffff166000526064602052615d7b611132615d6a6001600160a01b039361ffff600460e08760016040600020015416604051928380927f3850c7bd0000000000000000000000000000000000000000000000000000000082525afa908115615de2575b600091615dbe575b50828781168289161115615dae57615d6291615c98565b965b16615cb0565b6001600160a01b0361271091160490565b911611615d8457565b60046040517f07a1db07000000000000000000000000000000000000000000000000000000008152fd5b90615db891615c98565b96615d64565b615dd6915060e03d811161494c5761493a818361081c565b50505050505038615d4b565b615dea613795565b615d43565b615df7613f01565b9063ffffffff91828216600052606d60205260406000209280845416911614600014615e435750600101547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b61146f9150614403565b615e55613f01565b9063ffffffff808216600052606d60205280604060002054931690831614600014615e81575060201c90565b61146f9150613c6490614022565b805160051b810160209081018183015b818110615eac5750505090565b80515481528201615e9f565b9091615ed192811015615ed5575b60051b810190613965565b9091565b615edd612dc6565b615ec6565b908092918237016000815290565b60208183031261000e5780519067ffffffffffffffff821161000e570181601f8201121561000e578051615f2381614c4b565b92615f31604051948561081c565b8184526020828401011161000e5761146f9160208085019101610aa856fea2646970667358221220a17ee6737ebff31f3432faa264c9c3e22031a16d93c7a52c8d9f83bde14583db64736f6c634300080e0033", + "numDeployments": 2, + "solcInputHash": "22b7028cc81d5cf62f774cbaec4dae64", + "metadata": "{\"compiler\":{\"version\":\"0.8.14+commit.80d49f37\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"AccessDenied\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotPauseIfUnpauseInProgress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotUnpauseIfPauseInProgress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"collateralId\",\"type\":\"uint32\"}],\"name\":\"CollateralDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"collateralId\",\"type\":\"uint32\"}],\"name\":\"CollateralNotAllowedForUse\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"}],\"name\":\"IllegalSqrtPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"incorrectAddress\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"correctAddress\",\"type\":\"address\"}],\"name\":\"IncorrectCollateralAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"invalidAddress\",\"type\":\"address\"}],\"name\":\"InvalidCollateralAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum IClearingHouseEnums.MulticallOperationType\",\"name\":\"multicallOperationType\",\"type\":\"uint8\"}],\"name\":\"InvalidMulticallOperationType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"}],\"name\":\"InvalidSetting\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenLiquidationParameters\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"keeperFee\",\"type\":\"int256\"}],\"name\":\"KeeperFeeNotPositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"notionalValue\",\"type\":\"uint256\"}],\"name\":\"LowNotionalValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotRageTradeFactory\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"PoolNotAllowedForTrade\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SafeCast_UInt224Overflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SlippageBeyondTolerance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"T\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Unauthorised\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAmount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"ownerAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"}],\"name\":\"AccountCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"cToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForDeposit\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct IClearingHouseStructures.CollateralSettings\",\"name\":\"cTokenInfo\",\"type\":\"tuple\"}],\"name\":\"CollateralSettingsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernancePending\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernancePending\",\"type\":\"address\"}],\"name\":\"GovernancePending\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernance\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernance\",\"type\":\"address\"}],\"name\":\"GovernanceTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"PausedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"initialMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maintainanceMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maxVirtualPriceDeviationRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForTrade\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isCrossMargined\",\"type\":\"bool\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct IClearingHouseStructures.PoolSettings\",\"name\":\"settings\",\"type\":\"tuple\"}],\"name\":\"PoolSettingsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"rangeLiquidationFeeFraction\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"tokenLiquidationFeeFraction\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"closeFactorMMThresholdBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"partialLiquidationCloseFactorBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"insuranceFundFeeShareBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"liquidationSlippageSqrtToleranceBps\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"maxRangeLiquidationFees\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minNotionalLiquidatable\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"struct IClearingHouseStructures.LiquidationParams\",\"name\":\"liquidationParams\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"removeLimitOrderFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minimumOrderNotional\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minRequiredMargin\",\"type\":\"uint256\"}],\"name\":\"ProtocolSettingsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousTeamMultisigPending\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newTeamMultisigPending\",\"type\":\"address\"}],\"name\":\"TeamMultisigPending\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousTeamMultisig\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newTeamMultisig\",\"type\":\"address\"}],\"name\":\"TeamMultisigTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptGovernanceTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptTeamMultisigTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createAccount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"newAccountId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"collateralId\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"createAccountAndAddMargin\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"newAccountId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"extsload\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"val\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"slots\",\"type\":\"bytes32[]\"}],\"name\":\"extsload\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isInitialMargin\",\"type\":\"bool\"}],\"name\":\"getAccountMarketValueAndRequiredMargin\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"marketValue\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"requiredMargin\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"}],\"name\":\"getAccountNetProfit\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"accountNetProfit\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"getAccountNetTokenPosition\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"netPosition\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"getRealTwapPriceX128\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"realPriceX128\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"getVirtualTwapPriceX128\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"virtualPriceX128\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governance\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governancePending\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rageTradeFactoryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialGovernance\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialTeamMultisig\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"_defaultCollateralToken\",\"type\":\"address\"},{\"internalType\":\"contract IOracle\",\"name\":\"_defaultCollateralTokenOracle\",\"type\":\"address\"},{\"internalType\":\"contract IInsuranceFund\",\"name\":\"_insuranceFund\",\"type\":\"address\"},{\"internalType\":\"contract IVQuote\",\"name\":\"_vQuote\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newGovernancePending\",\"type\":\"address\"}],\"name\":\"initiateGovernanceTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTeamMultisigPending\",\"type\":\"address\"}],\"name\":\"initiateTeamMultisigTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"insuranceFund\",\"outputs\":[{\"internalType\":\"contract IInsuranceFund\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"}],\"name\":\"liquidateLiquidityPositions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"targetAccountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"}],\"name\":\"liquidateTokenPosition\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"keeperFee\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"enum IClearingHouseEnums.MulticallOperationType\",\"name\":\"operationType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct IClearingHouseStructures.MulticallOperation[]\",\"name\":\"operations\",\"type\":\"tuple[]\"}],\"name\":\"multicallWithSingleMarginCheck\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numAccounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfPoolsToUpdateInThisTx\",\"type\":\"uint256\"}],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rageTradeFactoryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IVToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"contract IUniswapV3Pool\",\"name\":\"vPool\",\"type\":\"address\"},{\"internalType\":\"contract IVPoolWrapper\",\"name\":\"vPoolWrapper\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"initialMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maintainanceMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maxVirtualPriceDeviationRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForTrade\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isCrossMargined\",\"type\":\"bool\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"internalType\":\"struct IClearingHouseStructures.PoolSettings\",\"name\":\"settings\",\"type\":\"tuple\"}],\"internalType\":\"struct IClearingHouseStructures.Pool\",\"name\":\"poolInfo\",\"type\":\"tuple\"}],\"name\":\"registerPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"}],\"name\":\"removeLimitOrder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"}],\"name\":\"settleProfit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"amount\",\"type\":\"int256\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceLimit\",\"type\":\"uint160\"},{\"internalType\":\"bool\",\"name\":\"isNotional\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isPartialAllowed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"settleProfit\",\"type\":\"bool\"}],\"internalType\":\"struct IClearingHouseStructures.SwapParams\",\"name\":\"swapParams\",\"type\":\"tuple\"}],\"name\":\"swapToken\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"vTokenAmountOut\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"vQuoteAmountOut\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamMultisig\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teamMultisigPending\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfPoolsToUpdateInThisTx\",\"type\":\"uint256\"}],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"cToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct IClearingHouseStructures.CollateralSettings\",\"name\":\"collateralSettings\",\"type\":\"tuple\"}],\"name\":\"updateCollateralSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"collateralId\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"amount\",\"type\":\"int256\"}],\"name\":\"updateMargin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"initialMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maintainanceMarginRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maxVirtualPriceDeviationRatioBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isAllowedForTrade\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isCrossMargined\",\"type\":\"bool\"},{\"internalType\":\"contract IOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"internalType\":\"struct IClearingHouseStructures.PoolSettings\",\"name\":\"newSettings\",\"type\":\"tuple\"}],\"name\":\"updatePoolSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"amount\",\"type\":\"int256\"}],\"name\":\"updateProfit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint16\",\"name\":\"rangeLiquidationFeeFraction\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"tokenLiquidationFeeFraction\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"closeFactorMMThresholdBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"partialLiquidationCloseFactorBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"insuranceFundFeeShareBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"liquidationSlippageSqrtToleranceBps\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"maxRangeLiquidationFees\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minNotionalLiquidatable\",\"type\":\"uint64\"}],\"internalType\":\"struct IClearingHouseStructures.LiquidationParams\",\"name\":\"_liquidationParams\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_removeLimitOrderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOrderNotional\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minRequiredMargin\",\"type\":\"uint256\"}],\"name\":\"updateProtocolSettings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"poolId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"int128\",\"name\":\"liquidityDelta\",\"type\":\"int128\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceCurrent\",\"type\":\"uint160\"},{\"internalType\":\"uint16\",\"name\":\"slippageToleranceBps\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"closeTokenPosition\",\"type\":\"bool\"},{\"internalType\":\"enum IClearingHouseEnums.LimitOrderType\",\"name\":\"limitOrderType\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"settleProfit\",\"type\":\"bool\"}],\"internalType\":\"struct IClearingHouseStructures.LiquidityChangeParams\",\"name\":\"liquidityChangeParams\",\"type\":\"tuple\"}],\"name\":\"updateRangeOrder\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"vTokenAmountOut\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"vQuoteAmountOut\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfPoolsToUpdateInThisTx\",\"type\":\"uint256\"}],\"name\":\"withdrawProtocolFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawUSDCToTeamMultisig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessDenied(address)\":[{\"params\":{\"senderAddress\":\"address of msg sender\"}}],\"CollateralDoesNotExist(uint32)\":[{\"params\":{\"collateralId\":\"address of token\"}}],\"CollateralNotAllowedForUse(uint32)\":[{\"params\":{\"collateralId\":\"address of token\"}}],\"IncorrectCollateralAddress(address,address)\":[{\"params\":{\"correctAddress\":\"correct address of collateral token\",\"incorrectAddress\":\"incorrect address of collateral token\"}}],\"InvalidCollateralAddress(address)\":[{\"params\":{\"invalidAddress\":\"invalid address of collateral token\"}}],\"InvalidMulticallOperationType(uint8)\":[{\"params\":{\"multicallOperationType\":\"is the value that is out of bounds\"}}],\"LowNotionalValue(uint256)\":[{\"params\":{\"notionalValue\":\"notional value of txn\"}}],\"PoolDoesNotExist(uint32)\":[{\"params\":{\"poolId\":\"unitialized truncated address supplied\"}}],\"PoolNotAllowedForTrade(uint32)\":[{\"params\":{\"poolId\":\"address of token\"}}]},\"kind\":\"dev\",\"methods\":{\"createAccount()\":{\"returns\":{\"newAccountId\":\"- serial number of the new account created\"}},\"createAccountAndAddMargin(uint32,uint256)\":{\"params\":{\"amount\":\"amount of token to deposit\",\"collateralId\":\"truncated address of collateral token to deposit\"},\"returns\":{\"newAccountId\":\"- serial number of the new account created\"}},\"extsload(bytes32)\":{\"params\":{\"slot\":\"to read from.\"},\"returns\":{\"val\":\"stored at the slot.\"}},\"extsload(bytes32[])\":{\"params\":{\"slots\":\"to read from.\"},\"returns\":{\"_0\":\"values stored at the slots.\"}},\"getAccountMarketValueAndRequiredMargin(uint256,bool)\":{\"details\":\"This method can be used to check if an account is under water or not. If accountMarketValue < requiredMargin then liquidation can take place.\",\"params\":{\"accountId\":\"the account id\",\"isInitialMargin\":\"true is initial margin, false is maintainance margin\"},\"returns\":{\"marketValue\":\"the market value of the account, due to collateral and positions\",\"requiredMargin\":\"margin needed due to positions\"}},\"getAccountNetProfit(uint256)\":{\"params\":{\"accountId\":\"the account id\"},\"returns\":{\"accountNetProfit\":\"the net profit of the account\"}},\"getAccountNetTokenPosition(uint256,uint32)\":{\"params\":{\"accountId\":\"the account id\",\"poolId\":\"the id of the pool (vETH, ... etc)\"},\"returns\":{\"netPosition\":\"the net position of the account\"}},\"getRealTwapPriceX128(uint32)\":{\"params\":{\"poolId\":\"the id of the pool\"},\"returns\":{\"realPriceX128\":\"the real price of the pool\"}},\"getVirtualTwapPriceX128(uint32)\":{\"params\":{\"poolId\":\"the id of the pool\"},\"returns\":{\"virtualPriceX128\":\"the virtual price of the pool\"}},\"initiateGovernanceTransfer(address)\":{\"params\":{\"newGovernancePending\":\"the new governance address\"}},\"initiateTeamMultisigTransfer(address)\":{\"params\":{\"newTeamMultisigPending\":\"the new team multisig address\"}},\"liquidateLiquidityPositions(uint256)\":{\"details\":\"removes all the active range positions and gives liquidator a percent of notional amount closed + fixedFee\",\"params\":{\"accountId\":\"account id\"}},\"liquidateTokenPosition(uint256,uint32)\":{\"details\":\"transfers the fraction of token position at a discount to current price to liquidators account and gives liquidator some fixedFee\",\"params\":{\"poolId\":\"truncated address of token to withdraw\",\"targetAccountId\":\"account id\"},\"returns\":{\"keeperFee\":\"- amount of fees transferred to keeper\"}},\"multicall(bytes[])\":{\"details\":\"The `msg.value` should not be trusted for any method callable from multicall.\",\"params\":{\"data\":\"The encoded function data for each of the calls to make to this contract\"},\"returns\":{\"results\":\"The results from each of the calls passed in via data\"}},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"removeLimitOrder(uint256,uint32,int24,int24)\":{\"details\":\"checks the position of current price relative to limit order and checks limitOrderType\",\"params\":{\"accountId\":\"account id\",\"poolId\":\"truncated address of token to withdraw\",\"tickLower\":\"liquidity change parameters\",\"tickUpper\":\"liquidity change parameters\"}},\"settleProfit(uint256)\":{\"params\":{\"accountId\":\"account id\"}},\"swapToken(uint256,uint32,(int256,uint160,bool,bool,bool))\":{\"params\":{\"accountId\":\"account id\",\"poolId\":\"truncated address of token to withdraw\",\"swapParams\":\"swap parameters\"}},\"updateMargin(uint256,uint32,int256)\":{\"params\":{\"accountId\":\"account id\",\"amount\":\"amount of token to deposit\",\"collateralId\":\"truncated address of token to deposit\"}},\"updatePoolSettings(uint32,(uint16,uint16,uint16,uint32,bool,bool,address))\":{\"params\":{\"newSettings\":\"updated rage trade pool settings\",\"poolId\":\"rage trade pool id\"}},\"updateProfit(uint256,int256)\":{\"params\":{\"accountId\":\"account id\",\"amount\":\"amount of token to withdraw\"}},\"updateRangeOrder(uint256,uint32,(int24,int24,int128,uint160,uint16,bool,uint8,bool))\":{\"params\":{\"accountId\":\"account id\",\"liquidityChangeParams\":\"liquidity change parameters\",\"poolId\":\"truncated address of token to withdraw\"}},\"withdrawProtocolFee(uint256)\":{\"params\":{\"numberOfPoolsToUpdateInThisTx\":\"number of pools to collect fees from\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"AccessDenied(address)\":[{\"notice\":\"error to denote invalid account access\"}],\"CannotPauseIfUnpauseInProgress()\":[{\"notice\":\"error to denote unpause is in progress, hence cannot pause\"}],\"CannotUnpauseIfPauseInProgress()\":[{\"notice\":\"error to denote pause is in progress, hence cannot unpause\"}],\"CollateralDoesNotExist(uint32)\":[{\"notice\":\"error to denote usage of uninitialized token\"}],\"CollateralNotAllowedForUse(uint32)\":[{\"notice\":\"error to denote usage of unsupported collateral token\"}],\"IncorrectCollateralAddress(address,address)\":[{\"notice\":\"error to denote incorrect address is supplied while updating collateral settings\"}],\"InvalidCollateralAddress(address)\":[{\"notice\":\"error to denote invalid address supplied as a collateral token\"}],\"InvalidMulticallOperationType(uint8)\":[{\"notice\":\"this is errored when the enum (uint8) value is out of bounds\"}],\"InvalidSetting(uint256)\":[{\"notice\":\"error to denote an invalid setting for parameters\"}],\"InvalidTokenLiquidationParameters()\":[{\"notice\":\"error to denote invalid token liquidation (fraction to liquidate> 1)\"}],\"KeeperFeeNotPositive(int256)\":[{\"notice\":\"error to denote that keeper fee is negative or zero\"}],\"LowNotionalValue(uint256)\":[{\"notice\":\"error to denote low notional value of txn\"}],\"NotRageTradeFactory()\":[{\"notice\":\"error to denote that caller is not ragetrade factory\"}],\"PoolDoesNotExist(uint32)\":[{\"notice\":\"error to denote usage of uninitialized pool\"}],\"PoolNotAllowedForTrade(uint32)\":[{\"notice\":\"error to denote usage of unsupported pool\"}],\"SlippageBeyondTolerance()\":[{\"notice\":\"error to denote slippage of txn beyond set threshold\"}],\"ZeroAmount()\":[{\"notice\":\"error to denote that zero amount is passed and it's prohibited\"}]},\"events\":{\"AccountCreated(address,uint256)\":{\"notice\":\"denotes new account creation\"},\"CollateralSettingsUpdated(address,(address,uint32,bool))\":{\"notice\":\"new collateral supported as margin\"},\"PoolSettingsUpdated(uint32,(uint16,uint16,uint16,uint32,bool,bool,address))\":{\"notice\":\"maintainance margin ratio of a pool changed\"},\"ProtocolSettingsUpdated((uint16,uint16,uint16,uint16,uint16,uint16,uint64,uint64),uint256,uint256,uint256)\":{\"notice\":\"protocol settings changed\"}},\"kind\":\"user\",\"methods\":{\"acceptGovernanceTransfer()\":{\"notice\":\"Completes governance transfer, on being called by _governancePending.\"},\"acceptTeamMultisigTransfer()\":{\"notice\":\"Completes teamMultisig transfer, on being called by _teamMultisigPending.\"},\"createAccount()\":{\"notice\":\"creates a new account and adds it to the accounts map\"},\"createAccountAndAddMargin(uint32,uint256)\":{\"notice\":\"creates a new account and deposits 'amount' of token associated with 'poolId'\"},\"extsload(bytes32)\":{\"notice\":\"Returns a value from the storage.\"},\"extsload(bytes32[])\":{\"notice\":\"Returns multiple values from storage.\"},\"getAccountMarketValueAndRequiredMargin(uint256,bool)\":{\"notice\":\"Gets the market value and required margin of an account\"},\"getAccountNetProfit(uint256)\":{\"notice\":\"Gets the net profit of an account\"},\"getAccountNetTokenPosition(uint256,uint32)\":{\"notice\":\"Gets the net position of an account\"},\"getRealTwapPriceX128(uint32)\":{\"notice\":\"Gets the real twap price from the respective oracle of the given poolId\"},\"getVirtualTwapPriceX128(uint32)\":{\"notice\":\"Gets the virtual twap price from the respective oracle of the given poolId\"},\"governance()\":{\"notice\":\"Returns the address of the current governance.\"},\"governancePending()\":{\"notice\":\"Returns the address of the current governance.\"},\"initialize(address,address,address,address,address,address,address)\":{\"notice\":\"SYSTEM FUNCTIONS\"},\"initiateGovernanceTransfer(address)\":{\"notice\":\"Initiates governance transfer to a new account (`newGovernancePending`).\"},\"initiateTeamMultisigTransfer(address)\":{\"notice\":\"Initiates teamMultisig transfer to a new account (`newTeamMultisigPending`).\"},\"liquidateLiquidityPositions(uint256)\":{\"notice\":\"keeper call for liquidation of range position\"},\"liquidateTokenPosition(uint256,uint32)\":{\"notice\":\"keeper call for liquidation of token position\"},\"multicall(bytes[])\":{\"notice\":\"Call multiple functions in the current contract and return the data from all of them if they all succeed\"},\"multicallWithSingleMarginCheck(uint256,(uint8,bytes)[])\":{\"notice\":\"MULTICALL\"},\"removeLimitOrder(uint256,uint32,int24,int24)\":{\"notice\":\"keeper call to remove a limit order\"},\"settleProfit(uint256)\":{\"notice\":\"settles the profit/loss made with the settlement token collateral deposits\"},\"swapToken(uint256,uint32,(int256,uint160,bool,bool,bool))\":{\"notice\":\"swaps token associated with 'poolId' by 'amount' (Long if amount>0 else Short)\"},\"teamMultisig()\":{\"notice\":\"Returns the address of the current team multisig.transferTeamMultisig\"},\"teamMultisigPending()\":{\"notice\":\"Returns the address of the current team multisig.transferTeamMultisig\"},\"updateCollateralSettings(address,(address,uint32,bool))\":{\"notice\":\"ADMIN FUNCTIONS\"},\"updateMargin(uint256,uint32,int256)\":{\"notice\":\"deposits 'amount' of token associated with 'poolId'\"},\"updatePoolSettings(uint32,(uint16,uint16,uint16,uint32,bool,bool,address))\":{\"notice\":\"updates the rage trade pool settings\"},\"updateProfit(uint256,int256)\":{\"notice\":\"withdraws 'amount' of settlement token from the profit made\"},\"updateRangeOrder(uint256,uint32,(int24,int24,int128,uint160,uint16,bool,uint8,bool))\":{\"notice\":\"updates range order of token associated with 'poolId' by 'liquidityDelta' (Adds if amount>0 else Removes)also can be used to update limitOrderType\"},\"withdrawProtocolFee(uint256)\":{\"notice\":\"withdraws protocol fees collected in the supplied wrappers to team multisig\"},\"withdrawUSDCToTeamMultisig()\":{\"notice\":\"WITHDRAWAL FUNCTION\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/protocol/clearinghouse/ClearingHouse.sol\":\"ClearingHouse\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":2000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the\\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() initializer {}\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\\n // contract may have been reentered.\\n require(_initializing ? _isConstructor() : !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} modifier, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n function _isConstructor() private view returns (bool) {\\n return !AddressUpgradeable.isContract(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x372b0bc04e3b4c074559bbbfb1317afddb56de5504158ca25a7f9cd403980445\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x041af89e5e60b74e1203d5a34614c9de379726f52ecb8cf064cab78b9fdcdf9d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\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\":\"0x55cf2bd9fc76704ddcdc19834cd288b7de00fc0f298a40ea16a954ae8991db2d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\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\":\"0xbbc8ac883ac3c0078ce5ad3e288fbb3ffcc8a30c3a98c0fda0114d64fc44fca2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\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\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a / b + (a % b == 0 ? 0 : 1);\\n }\\n}\\n\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport {IUniswapV3PoolImmutables} from './pool/IUniswapV3PoolImmutables.sol';\\nimport {IUniswapV3PoolState} from './pool/IUniswapV3PoolState.sol';\\nimport {IUniswapV3PoolDerivedState} from './pool/IUniswapV3PoolDerivedState.sol';\\nimport {IUniswapV3PoolActions} from './pool/IUniswapV3PoolActions.sol';\\nimport {IUniswapV3PoolOwnerActions} from './pool/IUniswapV3PoolOwnerActions.sol';\\nimport {IUniswapV3PoolErrors} from './pool/IUniswapV3PoolErrors.sol';\\nimport {IUniswapV3PoolEvents} from './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 IUniswapV3PoolErrors,\\n IUniswapV3PoolEvents\\n{\\n\\n}\\n\",\"keccak256\":\"0x4e64844c56061cd90e0a80de73534a9166704c43eed579eb83f90bc2780ce968\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/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-0.8-support/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-0.8-support/contracts/interfaces/pool/IUniswapV3PoolErrors.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Errors emitted by a pool\\n/// @notice Contains all events emitted by the pool\\ninterface IUniswapV3PoolErrors {\\n error LOK();\\n error TLU();\\n error TLM();\\n error TUM();\\n error AI();\\n error M0();\\n error M1();\\n error AS();\\n error IIA();\\n error L();\\n error F0();\\n error F1();\\n}\\n\",\"keccak256\":\"0xf80abf13fb1fafc127ba4e792f240dd8ea7c8c893978cdfd8439c27fae9a037b\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/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-0.8-support/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-0.8-support/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-0.8-support/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 /// @return 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 /// @return observationIndex The index of the last oracle observation that was written,\\n /// @return observationCardinality The current maximum number of observations stored in the pool,\\n /// @return observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n /// @return 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 /// @return The liquidity at the current price of the pool\\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 /// @return liquidityNet how much liquidity changes when the pool price crosses the tick,\\n /// @return feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n /// @return feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n /// @return tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n /// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n /// @return secondsOutside the seconds spent on the other side of the tick from the current tick,\\n /// @return 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 /// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n /// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n /// @return tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n /// @return 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 /// @return tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n /// @return secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n /// @return 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\":\"0x44fa2ce1182f6c2f6bead3d1737804bf7e112252ae86e0f2e92f9b8249603f43\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.4.0;\\n\\n/// @title FixedPoint128\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\nlibrary FixedPoint128 {\\n uint256 internal constant Q128 = 0x100000000000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x2d1f4f73ae0d8f0a210b8d30084659b57c56ac8f2f96011fca36f00a6d417178\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/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-0.8-support/contracts/libraries/FullMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.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 unchecked {\\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 = (0 - 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\\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 unchecked {\\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}\\n\",\"keccak256\":\"0x7825565a4bb2a34a1dc96bbfead755785dfb0df8ef81bd934c43023689685645\",\"license\":\"MIT\"},\"@uniswap/v3-core-0.8-support/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-0.8-support/contracts/libraries/SqrtPriceMath.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\nimport {SafeCast} from './SafeCast.sol';\\n\\nimport {FullMath} from './FullMath.sol';\\nimport {UnsafeMath} from './UnsafeMath.sol';\\nimport {FixedPoint96} from './FixedPoint96.sol';\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Contains the math that uses square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMath {\\n using SafeCast for uint256;\\n\\n /// @notice Gets the next sqrt price given a delta of token0\\n /// @dev Always rounds up, because in the exact output case (increasing price) we need to move the price at least\\n /// far enough to get the desired output amount, and in the exact input case (decreasing price) we need to move the\\n /// price less in order to not send too much output.\\n /// The most precise formula for this is liquidity * sqrtPX96 / (liquidity +- amount * sqrtPX96),\\n /// if this is impossible because of overflow, we calculate liquidity / (liquidity / sqrtPX96 +- amount).\\n /// @param sqrtPX96 The starting price, i.e. before accounting for the token0 delta\\n /// @param liquidity The amount of usable liquidity\\n /// @param amount How much of token0 to add or remove from virtual reserves\\n /// @param add Whether to add or remove the amount of token0\\n /// @return The price after adding or removing amount, depending on add\\n function getNextSqrtPriceFromAmount0RoundingUp(\\n uint160 sqrtPX96,\\n uint128 liquidity,\\n uint256 amount,\\n bool add\\n ) internal pure returns (uint160) {\\n // we short circuit amount == 0 because the result is otherwise not guaranteed to equal the input price\\n if (amount == 0) return sqrtPX96;\\n uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n\\n if (add) {\\n unchecked {\\n uint256 product;\\n if ((product = amount * sqrtPX96) / amount == sqrtPX96) {\\n uint256 denominator = numerator1 + product;\\n if (denominator >= numerator1)\\n // always fits in 160 bits\\n return uint160(FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator));\\n }\\n }\\n // denominator is checked for overflow\\n return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96) + amount));\\n } else {\\n unchecked {\\n uint256 product;\\n // if the product overflows, we know the denominator underflows\\n // in addition, we must check that the denominator does not underflow\\n require((product = amount * sqrtPX96) / amount == sqrtPX96 && numerator1 > product);\\n uint256 denominator = numerator1 - product;\\n return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator).toUint160();\\n }\\n }\\n }\\n\\n /// @notice Gets the next sqrt price given a delta of token1\\n /// @dev Always rounds down, because in the exact output case (decreasing price) we need to move the price at least\\n /// far enough to get the desired output amount, and in the exact input case (increasing price) we need to move the\\n /// price less in order to not send too much output.\\n /// The formula we compute is within <1 wei of the lossless version: sqrtPX96 +- amount / liquidity\\n /// @param sqrtPX96 The starting price, i.e., before accounting for the token1 delta\\n /// @param liquidity The amount of usable liquidity\\n /// @param amount How much of token1 to add, or remove, from virtual reserves\\n /// @param add Whether to add, or remove, the amount of token1\\n /// @return The price after adding or removing `amount`\\n function getNextSqrtPriceFromAmount1RoundingDown(\\n uint160 sqrtPX96,\\n uint128 liquidity,\\n uint256 amount,\\n bool add\\n ) internal pure returns (uint160) {\\n // if we're adding (subtracting), rounding down requires rounding the quotient down (up)\\n // in both cases, avoid a mulDiv for most inputs\\n if (add) {\\n uint256 quotient = (\\n amount <= type(uint160).max\\n ? (amount << FixedPoint96.RESOLUTION) / liquidity\\n : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\n );\\n\\n return (uint256(sqrtPX96) + quotient).toUint160();\\n } else {\\n uint256 quotient = (\\n amount <= type(uint160).max\\n ? UnsafeMath.divRoundingUp(amount << FixedPoint96.RESOLUTION, liquidity)\\n : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity)\\n );\\n\\n require(sqrtPX96 > quotient);\\n // always fits 160 bits\\n unchecked {\\n return uint160(sqrtPX96 - quotient);\\n }\\n }\\n }\\n\\n /// @notice Gets the next sqrt price given an input amount of token0 or token1\\n /// @dev Throws if price or liquidity are 0, or if the next price is out of bounds\\n /// @param sqrtPX96 The starting price, i.e., before accounting for the input amount\\n /// @param liquidity The amount of usable liquidity\\n /// @param amountIn How much of token0, or token1, is being swapped in\\n /// @param zeroForOne Whether the amount in is token0 or token1\\n /// @return sqrtQX96 The price after adding the input amount to token0 or token1\\n function getNextSqrtPriceFromInput(\\n uint160 sqrtPX96,\\n uint128 liquidity,\\n uint256 amountIn,\\n bool zeroForOne\\n ) internal pure returns (uint160 sqrtQX96) {\\n require(sqrtPX96 > 0);\\n require(liquidity > 0);\\n\\n // round to make sure that we don't pass the target price\\n return\\n zeroForOne\\n ? getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true)\\n : getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true);\\n }\\n\\n /// @notice Gets the next sqrt price given an output amount of token0 or token1\\n /// @dev Throws if price or liquidity are 0 or the next price is out of bounds\\n /// @param sqrtPX96 The starting price before accounting for the output amount\\n /// @param liquidity The amount of usable liquidity\\n /// @param amountOut How much of token0, or token1, is being swapped out\\n /// @param zeroForOne Whether the amount out is token0 or token1\\n /// @return sqrtQX96 The price after removing the output amount of token0 or token1\\n function getNextSqrtPriceFromOutput(\\n uint160 sqrtPX96,\\n uint128 liquidity,\\n uint256 amountOut,\\n bool zeroForOne\\n ) internal pure returns (uint160 sqrtQX96) {\\n require(sqrtPX96 > 0);\\n require(liquidity > 0);\\n\\n // round to make sure that we pass the target price\\n return\\n zeroForOne\\n ? getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false)\\n : getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false);\\n }\\n\\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 ) internal pure returns (uint256 amount0) {\\n unchecked {\\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\\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 ) internal pure returns (uint256 amount1) {\\n unchecked {\\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\\n /// @notice Helper that gets signed token0 delta\\n /// @param sqrtRatioAX96 A sqrt price\\n /// @param sqrtRatioBX96 Another sqrt price\\n /// @param liquidity The change in liquidity for which to compute the amount0 delta\\n /// @return amount0 Amount of token0 corresponding to the passed liquidityDelta between the two prices\\n function getAmount0Delta(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n int128 liquidity\\n ) internal pure returns (int256 amount0) {\\n unchecked {\\n return\\n liquidity < 0\\n ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n }\\n }\\n\\n /// @notice Helper that gets signed token1 delta\\n /// @param sqrtRatioAX96 A sqrt price\\n /// @param sqrtRatioBX96 Another sqrt price\\n /// @param liquidity The change in liquidity for which to compute the amount1 delta\\n /// @return amount1 Amount of token1 corresponding to the passed liquidityDelta between the two prices\\n function getAmount1Delta(\\n uint160 sqrtRatioAX96,\\n uint160 sqrtRatioBX96,\\n int128 liquidity\\n ) internal pure returns (int256 amount1) {\\n unchecked {\\n return\\n liquidity < 0\\n ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe73eb517e348c084771c6204eb698fce95657901454ad0f394acf5192b709b97\",\"license\":\"BUSL-1.1\"},\"@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity ^0.8.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 error T();\\n error R();\\n\\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 unchecked {\\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n if (absTick > uint256(int256(MAX_TICK))) revert T();\\n\\n uint256 ratio = absTick & 0x1 != 0\\n ? 0xfffcb933bd6fad37aa2d162d1a594001\\n : 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\\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 unchecked {\\n // second inequality must be < because the price can never reach the price at the max tick\\n if (!(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO)) revert 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}\\n\",\"keccak256\":\"0x5c57de03a91cc2ec8939865dbbcb0197bb6c353b711075eefd8e0fca5e102129\",\"license\":\"GPL-2.0-or-later\"},\"@uniswap/v3-core-0.8-support/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/IMulticall.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Multicall interface\\n/// @notice Enables calling multiple methods in a single call to the contract\\ninterface IMulticall {\\n /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed\\n /// @dev The `msg.value` should not be trusted for any method callable from multicall.\\n /// @param data The encoded function data for each of the calls to make to this contract\\n /// @return results The results from each of the calls passed in via data\\n function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0xa8f9d0061ee730a522dc4bae6bd5cabb3e997e2c5983da183e912bdca93dfa7b\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IClearingHouse.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IGovernable } from './IGovernable.sol';\\n\\nimport { IClearingHouseActions } from './clearinghouse/IClearingHouseActions.sol';\\nimport { IClearingHouseCustomErrors } from './clearinghouse/IClearingHouseCustomErrors.sol';\\nimport { IClearingHouseEnums } from './clearinghouse/IClearingHouseEnums.sol';\\nimport { IClearingHouseEvents } from './clearinghouse/IClearingHouseEvents.sol';\\nimport { IClearingHouseOwnerActions } from './clearinghouse/IClearingHouseOwnerActions.sol';\\nimport { IClearingHouseStructures } from './clearinghouse/IClearingHouseStructures.sol';\\nimport { IClearingHouseSystemActions } from './clearinghouse/IClearingHouseSystemActions.sol';\\nimport { IClearingHouseView } from './clearinghouse/IClearingHouseView.sol';\\n\\ninterface IClearingHouse is\\n IGovernable,\\n IClearingHouseEnums,\\n IClearingHouseStructures,\\n IClearingHouseActions,\\n IClearingHouseCustomErrors,\\n IClearingHouseEvents,\\n IClearingHouseOwnerActions,\\n IClearingHouseSystemActions,\\n IClearingHouseView\\n{}\\n\",\"keccak256\":\"0xefcfad57b4aee9e20f34bb2809f69fcea692f67344e301b321ae60fa79f27c21\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IExtsload.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\n/// @title This is an interface to read contract's state that supports extsload.\\ninterface IExtsload {\\n /// @notice Returns a value from the storage.\\n /// @param slot to read from.\\n /// @return value stored at the slot.\\n function extsload(bytes32 slot) external view returns (bytes32 value);\\n\\n /// @notice Returns multiple values from storage.\\n /// @param slots to read from.\\n /// @return values stored at the slots.\\n function extsload(bytes32[] memory slots) external view returns (bytes32[] memory);\\n}\\n\",\"keccak256\":\"0x9b2387dbfb081f98a6d21ed1b7297668cda241fc1cea540fc0127f140a982d17\",\"license\":\"MIT\"},\"contracts/interfaces/IGovernable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\ninterface IGovernable {\\n function governance() external view returns (address);\\n\\n function governancePending() external view returns (address);\\n\\n function teamMultisig() external view returns (address);\\n\\n function teamMultisigPending() external view returns (address);\\n\\n function initiateGovernanceTransfer(address newGovernancePending) external;\\n\\n function acceptGovernanceTransfer() external;\\n\\n function initiateTeamMultisigTransfer(address newTeamMultisigPending) external;\\n\\n function acceptTeamMultisigTransfer() external;\\n}\\n\",\"keccak256\":\"0x28ac4a7bea6877cc7f831047aea9a26d7d30f787f15b1773e020287d06f02b75\",\"license\":\"MIT\"},\"contracts/interfaces/IInsuranceFund.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\ninterface IInsuranceFund {\\n function initialize(\\n IERC20 settlementToken,\\n address clearingHouse,\\n string calldata name,\\n string calldata symbol\\n ) external;\\n\\n function claim(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x8ce253b8c14252cdb8a8607f0014dbd70d168b999c061da4db4959c91660bc87\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\ninterface IOracle {\\n function getTwapPriceX128(uint32 twapDuration) external view returns (uint256 priceX128);\\n}\\n\",\"keccak256\":\"0x0b868e6dbb5dbbe067f65dda1a2c405a124142dbd936deeb4cc995ceb9ab232e\",\"license\":\"MIT\"},\"contracts/interfaces/IVPoolWrapper.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { IVQuote } from './IVQuote.sol';\\nimport { IVToken } from './IVToken.sol';\\n\\ninterface IVPoolWrapper {\\n struct InitializeVPoolWrapperParams {\\n address clearingHouse; // address of clearing house contract (proxy)\\n IVToken vToken; // address of vToken contract\\n IVQuote vQuote; // address of vQuote contract\\n IUniswapV3Pool vPool; // address of Uniswap V3 Pool contract, created using vToken and vQuote\\n uint24 liquidityFeePips; // liquidity fee fraction (in 1e6)\\n uint24 protocolFeePips; // protocol fee fraction (in 1e6)\\n }\\n\\n struct SwapResult {\\n int256 amountSpecified; // amount of tokens/vQuote which were specified in the swap request\\n int256 vTokenIn; // actual amount of vTokens paid by account to the Pool\\n int256 vQuoteIn; // actual amount of vQuotes paid by account to the Pool\\n uint256 liquidityFees; // actual amount of fees paid by account to the Pool\\n uint256 protocolFees; // actual amount of fees paid by account to the Protocol\\n uint160 sqrtPriceX96Start; // sqrt price at the beginning of the swap\\n uint160 sqrtPriceX96End; // sqrt price at the end of the swap\\n }\\n\\n struct WrapperValuesInside {\\n int256 sumAX128; // sum of all the A terms in the pool\\n int256 sumBInsideX128; // sum of all the B terms in side the tick range in the pool\\n int256 sumFpInsideX128; // sum of all the Fp terms in side the tick range in the pool\\n uint256 sumFeeInsideX128; // sum of all the fee terms in side the tick range in the pool\\n }\\n\\n /// @notice Emitted whenever a swap takes place\\n /// @param swapResult the swap result values\\n event Swap(SwapResult swapResult);\\n\\n /// @notice Emitted whenever liquidity is added\\n /// @param tickLower the lower tick of the range\\n /// @param tickUpper the upper tick of the range\\n /// @param liquidity the amount of liquidity that was added\\n /// @param vTokenPrincipal the amount of vToken that was sent to UniswapV3Pool\\n /// @param vQuotePrincipal the mount of vQuote charged was sent to UniswapV3Pool\\n event Mint(int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 vTokenPrincipal, uint256 vQuotePrincipal);\\n\\n /// @notice Emitted whenever liquidity is removed\\n /// @param tickLower the lower tick of the range\\n /// @param tickUpper the upper tick of the range\\n /// @param liquidity the amount of liquidity that was removed\\n /// @param vTokenPrincipal the amount of vToken that was received from UniswapV3Pool\\n /// @param vQuotePrincipal the mount of vQuote charged was received from UniswapV3Pool\\n event Burn(int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 vTokenPrincipal, uint256 vQuotePrincipal);\\n\\n /// @notice Emitted whenever clearing house enquired about the accrued protocol fees\\n /// @param amount the amount of accrued protocol fees\\n event AccruedProtocolFeeCollected(uint256 amount);\\n\\n /// @notice Emitted when governance updates the liquidity fees\\n /// @param liquidityFeePips the new liquidity fee ratio\\n event LiquidityFeeUpdated(uint24 liquidityFeePips);\\n\\n /// @notice Emitted when governance updates the protocol fees\\n /// @param protocolFeePips the new protocol fee ratio\\n event ProtocolFeeUpdated(uint24 protocolFeePips);\\n\\n /// @notice Emitted when funding rate override is updated\\n /// @param fundingRateOverrideX128 the new funding rate override value\\n event FundingRateOverrideUpdated(int256 fundingRateOverrideX128);\\n\\n function initialize(InitializeVPoolWrapperParams memory params) external;\\n\\n function vPool() external view returns (IUniswapV3Pool);\\n\\n function getValuesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (WrapperValuesInside memory wrapperValuesInside);\\n\\n function getExtrapolatedValuesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (WrapperValuesInside memory wrapperValuesInside);\\n\\n function swap(\\n bool swapVTokenForVQuote, // zeroForOne\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96\\n ) external returns (SwapResult memory swapResult);\\n\\n function mint(\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity\\n )\\n external\\n returns (\\n uint256 vTokenPrincipal,\\n uint256 vQuotePrincipal,\\n WrapperValuesInside memory wrapperValuesInside\\n );\\n\\n function burn(\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 liquidity\\n )\\n external\\n returns (\\n uint256 vTokenPrincipal,\\n uint256 vQuotePrincipal,\\n WrapperValuesInside memory wrapperValuesInside\\n );\\n\\n function getSumAX128() external view returns (int256);\\n\\n function getExtrapolatedSumAX128() external view returns (int256);\\n\\n function liquidityFeePips() external view returns (uint24);\\n\\n function protocolFeePips() external view returns (uint24);\\n\\n /// @notice Used by clearing house to update funding rate when clearing house is paused or unpaused.\\n /// @param useZeroFundingRate: used to discount funding payment during the duration ch was paused.\\n function updateGlobalFundingState(bool useZeroFundingRate) external;\\n\\n /// @notice Used by clearing house to know how much protocol fee was collected.\\n /// @return accruedProtocolFeeLast amount of protocol fees accrued since last collection.\\n /// @dev Does not do any token transfer, just reduces the state in wrapper by accruedProtocolFeeLast.\\n /// Clearing house already has the amount of settlement tokens to send to treasury.\\n function collectAccruedProtocolFee() external returns (uint256 accruedProtocolFeeLast);\\n}\\n\",\"keccak256\":\"0x5f8ffc93fbd71f02a3da23e4b7f2c8d2b4d1f879fe31e6acdcfa787dffc3f72b\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/IVQuote.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\ninterface IVQuote is IERC20 {\\n function mint(address account, uint256 amount) external;\\n\\n function burn(uint256 amount) external;\\n\\n function authorize(address vPoolWrapper) external;\\n}\\n\",\"keccak256\":\"0x77c3c0e1a7a1b9a10633953ac4824f14007af94c323e545b5ff12ef271416774\",\"license\":\"MIT\"},\"contracts/interfaces/IVToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\ninterface IVToken is IERC20 {\\n function mint(address account, uint256 amount) external;\\n\\n function burn(uint256 amount) external;\\n\\n function setVPoolWrapper(address) external;\\n}\\n\",\"keccak256\":\"0x0ac091c87193f7a5703954bf6484f3a30310b414cdda75cd81a80df23035dfe2\",\"license\":\"MIT\"},\"contracts/interfaces/clearinghouse/IClearingHouseActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseActions is IClearingHouseStructures {\\n /// @notice creates a new account and adds it to the accounts map\\n /// @return newAccountId - serial number of the new account created\\n function createAccount() external returns (uint256 newAccountId);\\n\\n /// @notice deposits 'amount' of token associated with 'poolId'\\n /// @param accountId account id\\n /// @param collateralId truncated address of token to deposit\\n /// @param amount amount of token to deposit\\n function updateMargin(\\n uint256 accountId,\\n uint32 collateralId,\\n int256 amount\\n ) external;\\n\\n /// @notice creates a new account and deposits 'amount' of token associated with 'poolId'\\n /// @param collateralId truncated address of collateral token to deposit\\n /// @param amount amount of token to deposit\\n /// @return newAccountId - serial number of the new account created\\n function createAccountAndAddMargin(uint32 collateralId, uint256 amount) external returns (uint256 newAccountId);\\n\\n /// @notice withdraws 'amount' of settlement token from the profit made\\n /// @param accountId account id\\n /// @param amount amount of token to withdraw\\n function updateProfit(uint256 accountId, int256 amount) external;\\n\\n /// @notice settles the profit/loss made with the settlement token collateral deposits\\n /// @param accountId account id\\n function settleProfit(uint256 accountId) external;\\n\\n /// @notice swaps token associated with 'poolId' by 'amount' (Long if amount>0 else Short)\\n /// @param accountId account id\\n /// @param poolId truncated address of token to withdraw\\n /// @param swapParams swap parameters\\n function swapToken(\\n uint256 accountId,\\n uint32 poolId,\\n SwapParams memory swapParams\\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut);\\n\\n /// @notice updates range order of token associated with 'poolId' by 'liquidityDelta' (Adds if amount>0 else Removes)\\n /// @notice also can be used to update limitOrderType\\n /// @param accountId account id\\n /// @param poolId truncated address of token to withdraw\\n /// @param liquidityChangeParams liquidity change parameters\\n function updateRangeOrder(\\n uint256 accountId,\\n uint32 poolId,\\n LiquidityChangeParams calldata liquidityChangeParams\\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut);\\n\\n /// @notice keeper call to remove a limit order\\n /// @dev checks the position of current price relative to limit order and checks limitOrderType\\n /// @param accountId account id\\n /// @param poolId truncated address of token to withdraw\\n /// @param tickLower liquidity change parameters\\n /// @param tickUpper liquidity change parameters\\n function removeLimitOrder(\\n uint256 accountId,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper\\n ) external;\\n\\n /// @notice keeper call for liquidation of range position\\n /// @dev removes all the active range positions and gives liquidator a percent of notional amount closed + fixedFee\\n /// @param accountId account id\\n function liquidateLiquidityPositions(uint256 accountId) external;\\n\\n /// @notice keeper call for liquidation of token position\\n /// @dev transfers the fraction of token position at a discount to current price to liquidators account and gives liquidator some fixedFee\\n /// @param targetAccountId account id\\n /// @param poolId truncated address of token to withdraw\\n /// @return keeperFee - amount of fees transferred to keeper\\n function liquidateTokenPosition(uint256 targetAccountId, uint32 poolId) external returns (int256 keeperFee);\\n}\\n\",\"keccak256\":\"0x21b3310eeee56ef487f2a636019278dc6a59f9d1e40364989caf9013cee0de55\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseCustomErrors.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IVToken } from '../IVToken.sol';\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseCustomErrors is IClearingHouseStructures {\\n /// @notice error to denote invalid account access\\n /// @param senderAddress address of msg sender\\n error AccessDenied(address senderAddress);\\n\\n /// @notice error to denote usage of uninitialized token\\n /// @param collateralId address of token\\n error CollateralDoesNotExist(uint32 collateralId);\\n\\n /// @notice error to denote usage of unsupported collateral token\\n /// @param collateralId address of token\\n error CollateralNotAllowedForUse(uint32 collateralId);\\n\\n /// @notice error to denote unpause is in progress, hence cannot pause\\n error CannotPauseIfUnpauseInProgress();\\n\\n /// @notice error to denote pause is in progress, hence cannot unpause\\n error CannotUnpauseIfPauseInProgress();\\n\\n /// @notice error to denote incorrect address is supplied while updating collateral settings\\n /// @param incorrectAddress incorrect address of collateral token\\n /// @param correctAddress correct address of collateral token\\n error IncorrectCollateralAddress(IERC20 incorrectAddress, IERC20 correctAddress);\\n\\n /// @notice error to denote invalid address supplied as a collateral token\\n /// @param invalidAddress invalid address of collateral token\\n error InvalidCollateralAddress(address invalidAddress);\\n\\n /// @notice error to denote invalid token liquidation (fraction to liquidate> 1)\\n error InvalidTokenLiquidationParameters();\\n\\n /// @notice this is errored when the enum (uint8) value is out of bounds\\n /// @param multicallOperationType is the value that is out of bounds\\n error InvalidMulticallOperationType(MulticallOperationType multicallOperationType);\\n\\n /// @notice error to denote that keeper fee is negative or zero\\n error KeeperFeeNotPositive(int256 keeperFee);\\n\\n /// @notice error to denote low notional value of txn\\n /// @param notionalValue notional value of txn\\n error LowNotionalValue(uint256 notionalValue);\\n\\n /// @notice error to denote that caller is not ragetrade factory\\n error NotRageTradeFactory();\\n\\n /// @notice error to denote usage of uninitialized pool\\n /// @param poolId unitialized truncated address supplied\\n error PoolDoesNotExist(uint32 poolId);\\n\\n /// @notice error to denote usage of unsupported pool\\n /// @param poolId address of token\\n error PoolNotAllowedForTrade(uint32 poolId);\\n\\n /// @notice error to denote slippage of txn beyond set threshold\\n error SlippageBeyondTolerance();\\n\\n /// @notice error to denote that zero amount is passed and it's prohibited\\n error ZeroAmount();\\n\\n /// @notice error to denote an invalid setting for parameters\\n error InvalidSetting(uint256 errorCode);\\n}\\n\",\"keccak256\":\"0x0d0bafa321810a35b83b36d81507937ed5d132c65ee6ef05c92085bd31dd6ca8\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseEnums.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface IClearingHouseEnums {\\n enum LimitOrderType {\\n NONE,\\n LOWER_LIMIT,\\n UPPER_LIMIT\\n }\\n\\n enum MulticallOperationType {\\n UPDATE_MARGIN,\\n UPDATE_PROFIT,\\n SWAP_TOKEN,\\n UPDATE_RANGE_ORDER,\\n REMOVE_LIMIT_ORDER,\\n LIQUIDATE_LIQUIDITY_POSITIONS,\\n LIQUIDATE_TOKEN_POSITION\\n }\\n}\\n\",\"keccak256\":\"0xf9ad0cde3e59a661f70a3af28cc6f8cdba0bcfdbc2f8df3799a1e17c333db4b2\",\"license\":\"MIT\"},\"contracts/interfaces/clearinghouse/IClearingHouseEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IVToken } from '../IVToken.sol';\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseEvents is IClearingHouseStructures {\\n /// @notice denotes new account creation\\n /// @param ownerAddress wallet address of account owner\\n /// @param accountId serial number of the account\\n event AccountCreated(address indexed ownerAddress, uint256 accountId);\\n\\n /// @notice new collateral supported as margin\\n /// @param cTokenInfo collateral token info\\n event CollateralSettingsUpdated(IERC20 cToken, CollateralSettings cTokenInfo);\\n\\n /// @notice maintainance margin ratio of a pool changed\\n /// @param poolId id of the rage trade pool\\n /// @param settings new settings\\n event PoolSettingsUpdated(uint32 poolId, PoolSettings settings);\\n\\n /// @notice protocol settings changed\\n /// @param liquidationParams liquidation params\\n /// @param removeLimitOrderFee fee for remove limit order\\n /// @param minimumOrderNotional minimum order notional\\n /// @param minRequiredMargin minimum required margin\\n event ProtocolSettingsUpdated(\\n LiquidationParams liquidationParams,\\n uint256 removeLimitOrderFee,\\n uint256 minimumOrderNotional,\\n uint256 minRequiredMargin\\n );\\n\\n event PausedUpdated(bool paused);\\n}\\n\",\"keccak256\":\"0x40638408c2cf0484b8d11d937181711eb3ea61368133ed92134cd3a84cdf97e6\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseOwnerActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IVToken } from '../IVToken.sol';\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseOwnerActions is IClearingHouseStructures {\\n /// @notice updates the collataral settings\\n /// @param cToken collateral token\\n /// @param collateralSettings settings\\n function updateCollateralSettings(IERC20 cToken, CollateralSettings memory collateralSettings) external;\\n\\n /// @notice updates the rage trade pool settings\\n /// @param poolId rage trade pool id\\n /// @param newSettings updated rage trade pool settings\\n function updatePoolSettings(uint32 poolId, PoolSettings calldata newSettings) external;\\n\\n /// @notice updates the protocol settings\\n /// @param liquidationParams liquidation params\\n /// @param removeLimitOrderFee fee for remove limit order\\n /// @param minimumOrderNotional minimum order notional\\n /// @param minRequiredMargin minimum required margin\\n function updateProtocolSettings(\\n LiquidationParams calldata liquidationParams,\\n uint256 removeLimitOrderFee,\\n uint256 minimumOrderNotional,\\n uint256 minRequiredMargin\\n ) external;\\n\\n /// @notice withdraws protocol fees collected in the supplied wrappers to team multisig\\n /// @param numberOfPoolsToUpdateInThisTx number of pools to collect fees from\\n function withdrawProtocolFee(uint256 numberOfPoolsToUpdateInThisTx) external;\\n}\\n\",\"keccak256\":\"0x1aad0d196e372bca92b21b75013916fea6fdfd74ea000b9909cc4aa305364642\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseStructures.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { IOracle } from '../IOracle.sol';\\nimport { IVToken } from '../IVToken.sol';\\nimport { IVPoolWrapper } from '../IVPoolWrapper.sol';\\n\\nimport { IClearingHouseEnums } from './IClearingHouseEnums.sol';\\n\\ninterface IClearingHouseStructures is IClearingHouseEnums {\\n struct BalanceAdjustments {\\n int256 vQuoteIncrease; // specifies the increase in vQuote balance\\n int256 vTokenIncrease; // specifies the increase in token balance\\n int256 traderPositionIncrease; // specifies the increase in trader position\\n }\\n\\n struct Collateral {\\n IERC20 token; // address of the collateral token\\n CollateralSettings settings; // collateral settings, changable by governance later\\n }\\n\\n struct CollateralSettings {\\n IOracle oracle; // address of oracle which gives price to be used for collateral\\n uint32 twapDuration; // duration of the twap in seconds\\n bool isAllowedForDeposit; // whether the collateral is allowed to be deposited at the moment\\n }\\n\\n struct CollateralDepositView {\\n IERC20 collateral; // address of the collateral token\\n uint256 balance; // balance of the collateral in the account\\n }\\n\\n struct LiquidityChangeParams {\\n int24 tickLower; // tick lower of the range\\n int24 tickUpper; // tick upper of the range\\n int128 liquidityDelta; // positive to add liquidity, negative to remove liquidity\\n uint160 sqrtPriceCurrent; // hint for virtual price, to prevent sandwitch attack\\n uint16 slippageToleranceBps; // slippage tolerance in bps, to prevent sandwitch attack\\n bool closeTokenPosition; // whether to close the token position generated due to the liquidity change\\n LimitOrderType limitOrderType; // limit order type\\n bool settleProfit; // whether to settle profit against USDC margin\\n }\\n\\n struct LiquidityPositionView {\\n int24 tickLower; // tick lower of the range\\n int24 tickUpper; // tick upper of the range\\n uint128 liquidity; // liquidity in the range by the account\\n int256 vTokenAmountIn; // amount of token supplied by the account, to calculate net position\\n int256 sumALastX128; // checkpoint of the term A in funding payment math\\n int256 sumBInsideLastX128; // checkpoint of the term B in funding payment math\\n int256 sumFpInsideLastX128; // checkpoint of the term Fp in funding payment math\\n uint256 sumFeeInsideLastX128; // checkpoint of the trading fees\\n LimitOrderType limitOrderType; // limit order type\\n }\\n\\n struct LiquidationParams {\\n uint16 rangeLiquidationFeeFraction; // fraction of net token position rm from the range to be charged as liquidation fees (in 1e5)\\n uint16 tokenLiquidationFeeFraction; // fraction of traded amount of vquote to be charged as liquidation fees (in 1e5)\\n uint16 closeFactorMMThresholdBps; // fraction the MM threshold for partial liquidation (in 1e4)\\n uint16 partialLiquidationCloseFactorBps; // fraction the % of position to be liquidated if partial liquidation should occur (in 1e4)\\n uint16 insuranceFundFeeShareBps; // fraction of the fee share for insurance fund out of the total liquidation fee (in 1e4)\\n uint16 liquidationSlippageSqrtToleranceBps; // fraction of the max sqrt price slippage threshold (in 1e4) (can be set to - actual price slippage tolerance / 2)\\n uint64 maxRangeLiquidationFees; // maximum range liquidation fees (in settlement token amount decimals)\\n uint64 minNotionalLiquidatable; // minimum notional value of position for it to be eligible for partial liquidation (in settlement token amount decimals)\\n }\\n\\n struct MulticallOperation {\\n MulticallOperationType operationType; // operation type\\n bytes data; // abi encoded data for the operation\\n }\\n\\n struct Pool {\\n IVToken vToken; // address of the vToken, poolId = vToken.truncate()\\n IUniswapV3Pool vPool; // address of the UniswapV3Pool(token0=vToken, token1=vQuote, fee=500)\\n IVPoolWrapper vPoolWrapper; // wrapper address\\n PoolSettings settings; // pool settings, which can be updated by governance later\\n }\\n\\n struct PoolSettings {\\n uint16 initialMarginRatioBps; // margin ratio (1e4) considered for create/update position, removing margin or profit\\n uint16 maintainanceMarginRatioBps; // margin ratio (1e4) considered for liquidations by keeper\\n uint16 maxVirtualPriceDeviationRatioBps; // maximum deviation (1e4) from the current virtual price\\n uint32 twapDuration; // twap duration (seconds) for oracle\\n bool isAllowedForTrade; // whether the pool is allowed to be traded at the moment\\n bool isCrossMargined; // whether cross margined is done for positions of this pool\\n IOracle oracle; // spot price feed twap oracle for this pool\\n }\\n\\n struct SwapParams {\\n int256 amount; // amount of tokens/vQuote to swap\\n uint160 sqrtPriceLimit; // threshold sqrt price which should not be crossed\\n bool isNotional; // whether the amount represents vQuote amount\\n bool isPartialAllowed; // whether to end swap (partial) when sqrtPriceLimit is reached, instead of reverting\\n bool settleProfit; // whether to settle profit against USDC margin\\n }\\n\\n struct TickRange {\\n int24 tickLower;\\n int24 tickUpper;\\n }\\n\\n struct VTokenPositionView {\\n uint32 poolId; // id of the pool of which this token position is for\\n int256 balance; // vTokenLong - vTokenShort\\n int256 netTraderPosition; // net position due to trades and liquidity change carries\\n int256 sumALastX128; // checkoint of the term A in funding payment math\\n LiquidityPositionView[] liquidityPositions; // liquidity positions of the account in the pool\\n }\\n}\\n\",\"keccak256\":\"0x2898873034245bbb873b239ea1fe46b528897bc0018ccf46c2630f8f50e5cb25\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseSystemActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IInsuranceFund } from '../IInsuranceFund.sol';\\nimport { IOracle } from '../IOracle.sol';\\nimport { IVQuote } from '../IVQuote.sol';\\nimport { IVToken } from '../IVToken.sol';\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\n\\ninterface IClearingHouseSystemActions is IClearingHouseStructures {\\n /// @notice initializes clearing house contract\\n /// @param rageTradeFactoryAddress rage trade factory address\\n /// @param defaultCollateralToken address of default collateral token\\n /// @param defaultCollateralTokenOracle address of default collateral token oracle\\n /// @param insuranceFund address of insurance fund\\n /// @param vQuote address of vQuote\\n function initialize(\\n address rageTradeFactoryAddress,\\n address initialGovernance,\\n address initialTeamMultisig,\\n IERC20 defaultCollateralToken,\\n IOracle defaultCollateralTokenOracle,\\n IInsuranceFund insuranceFund,\\n IVQuote vQuote\\n ) external;\\n\\n function registerPool(Pool calldata poolInfo) external;\\n}\\n\",\"keccak256\":\"0x55af54c49f58ce14276954987014f03e878933ec0b51dca03e3cd2a2b99bd8d5\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/clearinghouse/IClearingHouseView.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\\nimport { IExtsload } from '../IExtsload.sol';\\n\\ninterface IClearingHouseView is IClearingHouseStructures, IExtsload {\\n /// @notice Gets the market value and required margin of an account\\n /// @dev This method can be used to check if an account is under water or not.\\n /// If accountMarketValue < requiredMargin then liquidation can take place.\\n /// @param accountId the account id\\n /// @param isInitialMargin true is initial margin, false is maintainance margin\\n /// @return accountMarketValue the market value of the account, due to collateral and positions\\n /// @return requiredMargin margin needed due to positions\\n function getAccountMarketValueAndRequiredMargin(uint256 accountId, bool isInitialMargin)\\n external\\n view\\n returns (int256 accountMarketValue, int256 requiredMargin);\\n\\n /// @notice Gets the net profit of an account\\n /// @param accountId the account id\\n /// @return accountNetProfit the net profit of the account\\n function getAccountNetProfit(uint256 accountId) external view returns (int256 accountNetProfit);\\n\\n /// @notice Gets the net position of an account\\n /// @param accountId the account id\\n /// @param poolId the id of the pool (vETH, ... etc)\\n /// @return netPosition the net position of the account\\n function getAccountNetTokenPosition(uint256 accountId, uint32 poolId) external view returns (int256 netPosition);\\n\\n /// @notice Gets the real twap price from the respective oracle of the given poolId\\n /// @param poolId the id of the pool\\n /// @return realPriceX128 the real price of the pool\\n function getRealTwapPriceX128(uint32 poolId) external view returns (uint256 realPriceX128);\\n\\n /// @notice Gets the virtual twap price from the respective oracle of the given poolId\\n /// @param poolId the id of the pool\\n /// @return virtualPriceX128 the virtual price of the pool\\n function getVirtualTwapPriceX128(uint32 poolId) external view returns (uint256 virtualPriceX128);\\n}\\n\",\"keccak256\":\"0xd9810b0098f0bc1999c4116f8125b4b2d20ff675c1f2a75c55dd1406fa6b0ecd\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/Account.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\n\\nimport { AddressHelper } from './AddressHelper.sol';\\nimport { CollateralDeposit } from './CollateralDeposit.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { SignedMath } from './SignedMath.sol';\\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\\nimport { LiquidityPosition } from './LiquidityPosition.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { VTokenPosition } from './VTokenPosition.sol';\\nimport { VTokenPositionSet } from './VTokenPositionSet.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\\nimport { IVQuote } from '../interfaces/IVQuote.sol';\\nimport { IVToken } from '../interfaces/IVToken.sol';\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Cross margined account functions\\n/// @dev This library is deployed and used as an external library by ClearingHouse contract.\\nlibrary Account {\\n using AddressHelper for address;\\n using FullMath for uint256;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n using SignedMath for int256;\\n\\n using Account for Account.Info;\\n using CollateralDeposit for CollateralDeposit.Set;\\n using LiquidityPositionSet for LiquidityPosition.Set;\\n using Protocol for Protocol.Info;\\n using VTokenPosition for VTokenPosition.Info;\\n using VTokenPositionSet for VTokenPosition.Set;\\n\\n /// @notice account info for user\\n /// @param owner specifies the account owner\\n /// @param tokenPositions is set of all open token positions\\n /// @param collateralDeposits is set of all deposits\\n struct Info {\\n uint96 id;\\n address owner;\\n VTokenPosition.Set tokenPositions;\\n CollateralDeposit.Set collateralDeposits;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n /**\\n * Errors\\n */\\n\\n /// @notice error to denote that there is not enough margin for the transaction to go through\\n /// @param accountMarketValue shows the account market value after the transaction is executed\\n /// @param totalRequiredMargin shows the total required margin after the transaction is executed\\n error InvalidTransactionNotEnoughMargin(int256 accountMarketValue, int256 totalRequiredMargin);\\n\\n /// @notice error to denote that there is not enough profit during profit withdrawal\\n /// @param totalProfit shows the value of positions at the time of execution after removing amount specified\\n error InvalidTransactionNotEnoughProfit(int256 totalProfit);\\n\\n /// @notice error to denote that there is enough margin, hence the liquidation is invalid\\n /// @param accountMarketValue shows the account market value before liquidation\\n /// @param totalRequiredMargin shows the total required margin before liquidation\\n error InvalidLiquidationAccountAboveWater(int256 accountMarketValue, int256 totalRequiredMargin);\\n\\n /// @notice error to denote that there are active ranges present during token liquidation, hence the liquidation is invalid\\n /// @param poolId shows the poolId for which range is active\\n error InvalidLiquidationActiveRangePresent(uint32 poolId);\\n\\n /// @notice denotes withdrawal of profit in settlement token\\n /// @param accountId serial number of the account\\n /// @param amount amount of profit withdrawn\\n event ProfitUpdated(uint256 indexed accountId, int256 amount);\\n\\n /**\\n * Events\\n */\\n\\n /// @notice denotes add or remove of margin\\n /// @param accountId serial number of the account\\n /// @param collateralId token in which margin is deposited\\n /// @param amount amount of tokens deposited\\n event MarginUpdated(uint256 indexed accountId, uint32 indexed collateralId, int256 amount, bool isSettleProfit);\\n\\n /// @notice denotes range position liquidation event\\n /// @dev all range positions are liquidated and the current tokens inside the range are added in as token positions to the account\\n /// @param accountId serial number of the account\\n /// @param keeperAddress address of keeper who performed the liquidation\\n /// @param liquidationFee total liquidation fee charged to the account\\n /// @param keeperFee total liquidaiton fee paid to the keeper (positive only)\\n /// @param insuranceFundFee total liquidaiton fee paid to the insurance fund (can be negative in case the account is not enought to cover the fee)\\n event LiquidityPositionsLiquidated(\\n uint256 indexed accountId,\\n address indexed keeperAddress,\\n int256 liquidationFee,\\n int256 keeperFee,\\n int256 insuranceFundFee,\\n int256 accountMarketValueFinal\\n );\\n\\n /// @notice denotes token position liquidation event\\n /// @dev the selected token position is take from the current account and moved to liquidatorAccount at a discounted prive to current pool price\\n /// @param accountId serial number of the account\\n /// @param poolId id of the rage trade pool for whose position was liquidated\\n /// @param keeperFee total liquidaiton fee paid to keeper\\n /// @param insuranceFundFee total liquidaiton fee paid to the insurance fund (can be negative in case the account is not enough to cover the fee)\\n event TokenPositionLiquidated(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int256 keeperFee,\\n int256 insuranceFundFee,\\n int256 accountMarketValueFinal\\n );\\n\\n /**\\n * External methods\\n */\\n\\n /// @notice changes deposit balance of 'vToken' by 'amount'\\n /// @param account account to deposit balance into\\n /// @param collateralId collateral id of the token\\n /// @param amount amount of token to deposit or withdraw\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n function updateMargin(\\n Account.Info storage account,\\n uint32 collateralId,\\n int256 amount,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n ) external {\\n _updateMargin(account, collateralId, amount, protocol, checkMargin, false);\\n }\\n\\n /// @notice updates 'amount' of profit generated in settlement token\\n /// @param account account to remove profit from\\n /// @param amount amount of profit(settlement token) to add/remove\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n function updateProfit(\\n Account.Info storage account,\\n int256 amount,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n ) external {\\n _updateProfit(account, amount, protocol, checkMargin);\\n }\\n\\n function settleProfit(Account.Info storage account, Protocol.Info storage protocol) external {\\n _settleProfit(account, protocol);\\n }\\n\\n /// @notice swaps 'vToken' of token amount equal to 'swapParams.amount'\\n /// @notice if vTokenAmount>0 then the swap is a long or close short and if vTokenAmount<0 then swap is a short or close long\\n /// @notice isNotional specifies whether the amount represents token amount (false) or vQuote amount(true)\\n /// @notice isPartialAllowed specifies whether to revert (false) or to execute a partial swap (true)\\n /// @notice sqrtPriceLimit threshold sqrt price which if crossed then revert or execute partial swap\\n /// @param account account to swap tokens for\\n /// @param poolId id of the pool to swap tokens for\\n /// @param swapParams parameters for the swap (Includes - amount, sqrtPriceLimit, isNotional, isPartialAllowed)\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n /// @return vTokenAmountOut amount of vToken after swap (user receiving then +ve, user paying then -ve)\\n /// @return vQuoteAmountOut amount of vQuote after swap (user receiving then +ve, user paying then -ve)\\n function swapToken(\\n Account.Info storage account,\\n uint32 poolId,\\n IClearingHouseStructures.SwapParams memory swapParams,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n // make a swap. vQuoteIn and vTokenAmountOut (in and out wrt uniswap).\\n // mints erc20 tokens in callback and send to the pool\\n (vTokenAmountOut, vQuoteAmountOut) = account.tokenPositions.swapToken(account.id, poolId, swapParams, protocol);\\n\\n if (swapParams.settleProfit) {\\n account._settleProfit(protocol);\\n }\\n // after all the stuff, account should be above water\\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\\n }\\n\\n /// @notice changes range liquidity 'vToken' of market value equal to 'vTokenNotional'\\n /// @notice if 'liquidityDelta'>0 then liquidity is added and if 'liquidityChange'<0 then liquidity is removed\\n /// @notice the liquidity change is reverted if the sqrt price at the time of execution is beyond 'slippageToleranceBps' of 'sqrtPriceCurrent' supplied\\n /// @notice whenever liquidity change is done the external token position is taken out. If 'closeTokenPosition' is true this is swapped out else it is added to the current token position\\n /// @param account account to change liquidity\\n /// @param poolId id of the rage trade pool\\n /// @param liquidityChangeParams parameters including lower tick, upper tick, liquidity delta, sqrtPriceCurrent, slippageToleranceBps, closeTokenPosition, limit order type\\n /// @param protocol set of all constants and token addresses\\n function liquidityChange(\\n Account.Info storage account,\\n uint32 poolId,\\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n )\\n external\\n returns (\\n int256 vTokenAmountOut,\\n int256 vQuoteAmountOut,\\n uint256 notionalValueAbs\\n )\\n {\\n // mint/burn tokens + fee + funding payment\\n (vTokenAmountOut, vQuoteAmountOut) = account.tokenPositions.liquidityChange(\\n account.id,\\n poolId,\\n liquidityChangeParams,\\n protocol\\n );\\n\\n if (liquidityChangeParams.settleProfit) {\\n account._settleProfit(protocol);\\n }\\n // after all the stuff, account should be above water\\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\\n\\n notionalValueAbs = protocol.getNotionalValue(poolId, vTokenAmountOut, vQuoteAmountOut);\\n }\\n\\n /// @notice liquidates all range positions in case the account is under water\\n /// charges a liquidation fee to the account and pays partially to the insurance fund and rest to the keeper.\\n /// @dev insurance fund covers the remaining fee if the account market value is not enough\\n /// @param account account to liquidate\\n /// @param protocol set of all constants and token addresses\\n /// @return keeperFee amount of liquidation fee paid to keeper\\n /// @return insuranceFundFee amount of liquidation fee paid to insurance fund\\n /// @return accountMarketValue account market value before liquidation\\n function liquidateLiquidityPositions(Account.Info storage account, Protocol.Info storage protocol)\\n external\\n returns (\\n int256 keeperFee,\\n int256 insuranceFundFee,\\n int256 accountMarketValue\\n )\\n {\\n // check basis maintanace margin\\n int256 totalRequiredMargin;\\n uint256 notionalAmountClosed;\\n\\n (accountMarketValue, totalRequiredMargin) = account._getAccountValueAndRequiredMargin(false, protocol);\\n\\n // check and revert if account is above water\\n if (accountMarketValue > totalRequiredMargin) {\\n revert InvalidLiquidationAccountAboveWater(accountMarketValue, totalRequiredMargin);\\n }\\n // liquidate all liquidity positions\\n notionalAmountClosed = account.tokenPositions.liquidateLiquidityPositions(account.id, protocol);\\n\\n // compute liquidation fees\\n (keeperFee, insuranceFundFee) = _computeLiquidationFees(\\n accountMarketValue,\\n notionalAmountClosed,\\n true,\\n protocol.liquidationParams\\n );\\n\\n account._updateVQuoteBalance(-(keeperFee + insuranceFundFee));\\n }\\n\\n /// @notice liquidates token position specified by 'poolId' in case account is underwater\\n /// charges a liquidation fee to the account and pays partially to the insurance fund and rest to the keeper.\\n /// @dev closes position uptil a specified slippage threshold in protocol.liquidationParams\\n /// @dev insurance fund covers the remaining fee if the account market value is not enough\\n /// @dev if there is range position this reverts (liquidators are supposed to liquidate range positions first)\\n /// @param account account to liquidate\\n /// @param poolId id of the pool to liquidate\\n /// @param protocol set of all constants and token addresses\\n /// @return keeperFee amount of liquidation fee paid to keeper\\n /// @return insuranceFundFee amount of liquidation fee paid to insurance fund\\n function liquidateTokenPosition(\\n Account.Info storage account,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) external returns (int256 keeperFee, int256 insuranceFundFee) {\\n bool isPartialLiquidation;\\n\\n // check if there is range position and revert\\n if (account.tokenPositions.isTokenRangeActive(poolId)) revert InvalidLiquidationActiveRangePresent(poolId);\\n\\n {\\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\\n false,\\n protocol\\n );\\n\\n // check and revert if account is above water\\n if (accountMarketValue > totalRequiredMargin) {\\n revert InvalidLiquidationAccountAboveWater(accountMarketValue, totalRequiredMargin);\\n } else if (\\n // check if account is underwater but within partial liquidation threshold\\n accountMarketValue >\\n totalRequiredMargin.mulDiv(protocol.liquidationParams.closeFactorMMThresholdBps, 1e4)\\n ) {\\n isPartialLiquidation = true;\\n }\\n }\\n\\n int256 tokensToTrade;\\n {\\n // get the net token position and tokensToTrade = -tokenPosition\\n // since no ranges are supposed to be there so only tokenPosition is in vTokenPositionSet\\n VTokenPosition.Info storage vTokenPosition = account.tokenPositions.getTokenPosition(poolId, false);\\n tokensToTrade = -vTokenPosition.balance;\\n uint256 tokenNotionalValue = tokensToTrade.absUint().mulDiv(\\n protocol.getCachedVirtualTwapPriceX128(poolId),\\n FixedPoint128.Q128\\n );\\n\\n // check if the token position is less than a certain notional value\\n // if so then liquidate the whole position even if partial liquidation is allowed\\n // otherwise do partial liquidation\\n if (isPartialLiquidation && tokenNotionalValue > protocol.liquidationParams.minNotionalLiquidatable) {\\n tokensToTrade = tokensToTrade.mulDiv(protocol.liquidationParams.partialLiquidationCloseFactorBps, 1e4);\\n }\\n }\\n\\n int256 accountMarketValueFinal;\\n {\\n uint160 sqrtPriceLimit;\\n {\\n // calculate sqrt price limit based on slippage threshold\\n uint160 sqrtTwapPrice = protocol.getVirtualTwapSqrtPriceX96(poolId);\\n if (tokensToTrade > 0) {\\n sqrtPriceLimit = uint256(sqrtTwapPrice)\\n .mulDiv(1e4 + protocol.liquidationParams.liquidationSlippageSqrtToleranceBps, 1e4)\\n .toUint160();\\n } else {\\n sqrtPriceLimit = uint256(sqrtTwapPrice)\\n .mulDiv(1e4 - protocol.liquidationParams.liquidationSlippageSqrtToleranceBps, 1e4)\\n .toUint160();\\n }\\n }\\n\\n // close position uptil sqrt price limit\\n (, int256 vQuoteAmountSwapped) = account.tokenPositions.swapToken(\\n account.id,\\n poolId,\\n IClearingHouseStructures.SwapParams({\\n amount: tokensToTrade,\\n sqrtPriceLimit: sqrtPriceLimit,\\n isNotional: false,\\n isPartialAllowed: true,\\n settleProfit: false\\n }),\\n protocol\\n );\\n\\n // get the account market value after closing the position\\n accountMarketValueFinal = account._getAccountValue(protocol);\\n\\n // compute liquidation fees\\n (keeperFee, insuranceFundFee) = _computeLiquidationFees(\\n accountMarketValueFinal,\\n vQuoteAmountSwapped.absUint(),\\n false,\\n protocol.liquidationParams\\n );\\n }\\n\\n // deduct liquidation fees from account\\n account._updateVQuoteBalance(-(keeperFee + insuranceFundFee));\\n\\n emit TokenPositionLiquidated(account.id, poolId, keeperFee, insuranceFundFee, accountMarketValueFinal);\\n }\\n\\n /// @notice removes limit order based on the current price position (keeper call)\\n /// @param account account to liquidate\\n /// @param poolId id of the pool for the range\\n /// @param tickLower lower tick index for the range\\n /// @param tickUpper upper tick index for the range\\n /// @param protocol platform constants\\n function removeLimitOrder(\\n Account.Info storage account,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n uint256 limitOrderFee,\\n Protocol.Info storage protocol\\n ) external {\\n account.tokenPositions.removeLimitOrder(account.id, poolId, tickLower, tickUpper, protocol);\\n\\n account._updateVQuoteBalance(-int256(limitOrderFee));\\n }\\n\\n /**\\n * External view methods\\n */\\n\\n /// @notice returns market value for the account positions based on current market conditions\\n /// @param account account to check\\n /// @param protocol set of all constants and token addresses\\n /// @return accountPositionProfits total market value of all the positions (token ) and deposits\\n function getAccountPositionProfits(Account.Info storage account, Protocol.Info storage protocol)\\n external\\n view\\n returns (int256 accountPositionProfits)\\n {\\n return account._getAccountPositionProfits(protocol);\\n }\\n\\n /// @notice returns market value and required margin for the account based on current market conditions\\n /// @dev (In case requiredMargin < minRequiredMargin then requiredMargin = minRequiredMargin)\\n /// @param account account to check\\n /// @param isInitialMargin true to use initial margin factor and false to use maintainance margin factor for calcualtion of required margin\\n /// @param protocol set of all constants and token addresses\\n /// @return accountMarketValue total market value of all the positions (token ) and deposits\\n /// @return totalRequiredMargin total margin required to keep the account above selected margin requirement (intial/maintainance)\\n function getAccountValueAndRequiredMargin(\\n Account.Info storage account,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) external view returns (int256 accountMarketValue, int256 totalRequiredMargin) {\\n return account._getAccountValueAndRequiredMargin(isInitialMargin, protocol);\\n }\\n\\n /// @notice checks if market value > required margin else revert with InvalidTransactionNotEnoughMargin\\n /// @param account account to check\\n /// @param isInitialMargin true to use initialMarginFactor and false to use maintainance margin factor for calcualtion of required margin\\n /// @param protocol set of all constants and token addresses\\n function checkIfMarginAvailable(\\n Account.Info storage account,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) external view {\\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\\n isInitialMargin,\\n protocol\\n );\\n if (accountMarketValue < totalRequiredMargin)\\n revert InvalidTransactionNotEnoughMargin(accountMarketValue, totalRequiredMargin);\\n }\\n\\n /// @notice checks if profit is available to withdraw settlement token (token value of all positions > 0) else revert with InvalidTransactionNotEnoughProfit\\n /// @param account account to check\\n /// @param protocol set of all constants and token addresses\\n function checkIfProfitAvailable(Account.Info storage account, Protocol.Info storage protocol) external view {\\n _checkIfProfitAvailable(account, protocol);\\n }\\n\\n /// @notice gets information about all the collateral and positions in the account\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n /// @return owner of the account\\n /// @return vQuoteBalance amount of vQuote in the account\\n /// @return collateralDeposits list of all the collateral amounts\\n /// @return tokenPositions list of all the token and liquidity positions\\n function getInfo(Account.Info storage account, Protocol.Info storage protocol)\\n external\\n view\\n returns (\\n address owner,\\n int256 vQuoteBalance,\\n IClearingHouseStructures.CollateralDepositView[] memory collateralDeposits,\\n IClearingHouseStructures.VTokenPositionView[] memory tokenPositions\\n )\\n {\\n owner = account.owner;\\n collateralDeposits = account.collateralDeposits.getInfo(protocol);\\n (vQuoteBalance, tokenPositions) = account.tokenPositions.getInfo();\\n }\\n\\n /// @notice gets the net position of the account for a given pool\\n /// @param account ref to the account state\\n /// @param poolId id of the pool\\n /// @param protocol ref to the protocol state\\n /// @return netPosition net position of the account for the pool\\n function getNetPosition(\\n Account.Info storage account,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) external view returns (int256 netPosition) {\\n return account.tokenPositions.getNetPosition(poolId, protocol);\\n }\\n\\n /**\\n * Internal methods\\n */\\n\\n function updateAccountPoolPrices(Account.Info storage account, Protocol.Info storage protocol) internal {\\n account.tokenPositions.updateOpenPoolPrices(protocol);\\n }\\n\\n /// @notice settles profit or loss for the account\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n function _settleProfit(Account.Info storage account, Protocol.Info storage protocol) internal {\\n int256 profits = account._getAccountPositionProfits(protocol);\\n uint32 settlementCollateralId = AddressHelper.truncate(protocol.settlementToken);\\n if (profits > 0) {\\n account._updateProfit(-profits, protocol, false);\\n account._updateMargin({\\n collateralId: settlementCollateralId,\\n amount: profits,\\n protocol: protocol,\\n checkMargin: false,\\n isSettleProfit: true\\n });\\n } else if (profits < 0) {\\n uint256 balance = account.collateralDeposits.getBalance(settlementCollateralId);\\n uint256 profitAbsUint = uint256(-profits);\\n uint256 balanceToUpdate = balance > profitAbsUint ? profitAbsUint : balance;\\n if (balanceToUpdate > 0) {\\n account._updateMargin({\\n collateralId: settlementCollateralId,\\n amount: -balanceToUpdate.toInt256(),\\n protocol: protocol,\\n checkMargin: false,\\n isSettleProfit: true\\n });\\n account._updateProfit(balanceToUpdate.toInt256(), protocol, false);\\n }\\n }\\n }\\n\\n /// @notice updates 'amount' of profit generated in settlement token\\n /// @param account account to remove profit from\\n /// @param amount amount of profit(settlement token) to add/remove\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n function _updateProfit(\\n Account.Info storage account,\\n int256 amount,\\n Protocol.Info storage protocol,\\n bool checkMargin\\n ) internal {\\n account._updateVQuoteBalance(amount);\\n\\n if (checkMargin && amount < 0) {\\n account._checkIfProfitAvailable(protocol);\\n account._checkIfMarginAvailable(true, protocol);\\n }\\n\\n emit ProfitUpdated(account.id, amount);\\n }\\n\\n /// @notice changes deposit balance of 'vToken' by 'amount'\\n /// @param account account to deposit balance into\\n /// @param collateralId collateral id of the token\\n /// @param amount amount of token to deposit or withdraw\\n /// @param protocol set of all constants and token addresses\\n /// @param checkMargin true to check if margin is available else false\\n function _updateMargin(\\n Account.Info storage account,\\n uint32 collateralId,\\n int256 amount,\\n Protocol.Info storage protocol,\\n bool checkMargin,\\n bool isSettleProfit\\n ) internal {\\n if (amount > 0) {\\n account.collateralDeposits.increaseBalance(collateralId, uint256(amount));\\n } else {\\n account.collateralDeposits.decreaseBalance(collateralId, uint256(-amount));\\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\\n }\\n\\n emit MarginUpdated(account.id, collateralId, amount, isSettleProfit);\\n }\\n\\n /// @notice updates the vQuote balance for 'account' by 'amount'\\n /// @param account pointer to 'account' struct\\n /// @param amount amount of balance to update\\n /// @return balanceAdjustments vToken and vQuote balance changes of the account\\n function _updateVQuoteBalance(Account.Info storage account, int256 amount)\\n internal\\n returns (IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments)\\n {\\n balanceAdjustments = IClearingHouseStructures.BalanceAdjustments(amount, 0, 0);\\n account.tokenPositions.vQuoteBalance += balanceAdjustments.vQuoteIncrease;\\n }\\n\\n /**\\n * Internal view methods\\n */\\n\\n /// @notice ensures that the account has enough margin to cover the required margin\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n function _checkIfMarginAvailable(\\n Account.Info storage account,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) internal view {\\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\\n isInitialMargin,\\n protocol\\n );\\n if (accountMarketValue < totalRequiredMargin)\\n revert InvalidTransactionNotEnoughMargin(accountMarketValue, totalRequiredMargin);\\n }\\n\\n /// @notice ensures that the account has non negative profit\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n function _checkIfProfitAvailable(Account.Info storage account, Protocol.Info storage protocol) internal view {\\n int256 totalPositionValue = account._getAccountPositionProfits(protocol);\\n if (totalPositionValue < 0) revert InvalidTransactionNotEnoughProfit(totalPositionValue);\\n }\\n\\n /// @notice gets the amount of account's position profits\\n /// @param account ref to the account state\\n /// @param protocol ref to the protocol state\\n function _getAccountPositionProfits(Account.Info storage account, Protocol.Info storage protocol)\\n internal\\n view\\n returns (int256 accountPositionProfits)\\n {\\n accountPositionProfits = account.tokenPositions.getAccountMarketValue(protocol);\\n }\\n\\n /// @notice gets market value for the account based on current market conditions\\n /// @param account ref to the account state\\n /// @param protocol set of all constants and token addresses\\n /// @return accountMarketValue total market value of all the positions (token ) and deposits\\n function _getAccountValue(Account.Info storage account, Protocol.Info storage protocol)\\n internal\\n view\\n returns (int256 accountMarketValue)\\n {\\n accountMarketValue = account._getAccountPositionProfits(protocol);\\n accountMarketValue += account.collateralDeposits.marketValue(protocol);\\n return (accountMarketValue);\\n }\\n\\n /// @notice gets market value and req margin for the account based on current market conditions\\n /// @param account ref to the account state\\n /// @param isInitialMargin true to use initialMarginFactor and false to use maintainance margin factor for calcualtion of required margin\\n /// @param protocol set of all constants and token addresses\\n /// @return accountMarketValue total market value of all the positions (token) and deposits\\n /// @return totalRequiredMargin total required margin for the account\\n function _getAccountValueAndRequiredMargin(\\n Account.Info storage account,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 accountMarketValue, int256 totalRequiredMargin) {\\n accountMarketValue = account._getAccountValue(protocol);\\n\\n totalRequiredMargin = account.tokenPositions.getRequiredMargin(isInitialMargin, protocol);\\n if (!account.tokenPositions.isEmpty()) {\\n totalRequiredMargin = totalRequiredMargin < int256(protocol.minRequiredMargin)\\n ? int256(protocol.minRequiredMargin)\\n : totalRequiredMargin;\\n }\\n return (accountMarketValue, totalRequiredMargin);\\n }\\n\\n /// @notice checks if 'account' is initialized\\n /// @param account pointer to 'account' struct\\n function _isInitialized(Account.Info storage account) internal view returns (bool) {\\n return !account.owner.isZero();\\n }\\n\\n /**\\n * Internal pure methods\\n */\\n\\n /// @notice computes keeper fee and insurance fund fee in case of liquidity position liquidation\\n /// @dev keeperFee = liquidationFee*(1-insuranceFundFeeShare)\\n /// @dev insuranceFundFee = accountMarketValue - keeperFee (if accountMarketValue is not enough to cover the fees) else insurancFundFee = liquidationFee - keeperFee\\n /// @param accountMarketValue market value of account\\n /// @param notionalAmountClosed notional value of position closed\\n /// @param isRangeLiquidation - true for range liquidation and false for token liquidation\\n /// @param liquidationParams parameters including insuranceFundFeeShareBps\\n /// @return keeperFee map of vTokens allowed on the platform\\n /// @return insuranceFundFee poolwrapper for token\\n function _computeLiquidationFees(\\n int256 accountMarketValue,\\n uint256 notionalAmountClosed,\\n bool isRangeLiquidation,\\n IClearingHouseStructures.LiquidationParams memory liquidationParams\\n ) internal pure returns (int256 keeperFee, int256 insuranceFundFee) {\\n uint256 liquidationFee;\\n\\n if (isRangeLiquidation) {\\n liquidationFee = notionalAmountClosed.mulDiv(liquidationParams.rangeLiquidationFeeFraction, 1e5);\\n if (liquidationParams.maxRangeLiquidationFees < liquidationFee)\\n liquidationFee = liquidationParams.maxRangeLiquidationFees;\\n } else {\\n liquidationFee = notionalAmountClosed.mulDiv(liquidationParams.tokenLiquidationFeeFraction, 1e5);\\n }\\n\\n int256 liquidationFeeInt = liquidationFee.toInt256();\\n\\n keeperFee = liquidationFeeInt.mulDiv(1e4 - liquidationParams.insuranceFundFeeShareBps, 1e4);\\n if (accountMarketValue - liquidationFeeInt < 0) {\\n insuranceFundFee = accountMarketValue - keeperFee;\\n } else {\\n insuranceFundFee = liquidationFeeInt - keeperFee;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x64e2fafb0b8e346baded62ab407edea1bcc6526bb35a1edadd9a79fcf02f7706\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/AddressHelper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport { IVToken } from '../interfaces/IVToken.sol';\\n\\n/// @title Address helper functions\\nlibrary AddressHelper {\\n /// @notice converts address to uint32, using the least significant 32 bits\\n /// @param addr Address to convert\\n /// @return truncated last 4 bytes of the address\\n function truncate(address addr) internal pure returns (uint32 truncated) {\\n assembly {\\n truncated := and(addr, 0xffffffff)\\n }\\n }\\n\\n /// @notice converts IERC20 contract to uint32\\n /// @param addr contract\\n /// @return truncated last 4 bytes of the address\\n function truncate(IERC20 addr) internal pure returns (uint32 truncated) {\\n return truncate(address(addr));\\n }\\n\\n /// @notice checks if two addresses are equal\\n /// @param a first address\\n /// @param b second address\\n /// @return true if addresses are equal\\n function eq(address a, address b) internal pure returns (bool) {\\n return a == b;\\n }\\n\\n /// @notice checks if addresses of two IERC20 contracts are equal\\n /// @param a first contract\\n /// @param b second contract\\n /// @return true if addresses are equal\\n function eq(IERC20 a, IERC20 b) internal pure returns (bool) {\\n return eq(address(a), address(b));\\n }\\n\\n /// @notice checks if an address is zero\\n /// @param a address to check\\n /// @return true if address is zero\\n function isZero(address a) internal pure returns (bool) {\\n return a == address(0);\\n }\\n\\n /// @notice checks if address of an IERC20 contract is zero\\n /// @param a contract to check\\n /// @return true if address is zero\\n function isZero(IERC20 a) internal pure returns (bool) {\\n return isZero(address(a));\\n }\\n}\\n\",\"keccak256\":\"0xe4a82de57fe35749b5baf34991cea5356c55dc015d58514a758adafe28af8686\",\"license\":\"MIT\"},\"contracts/libraries/BatchedLoop.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { Math } from '@openzeppelin/contracts/utils/math/Math.sol';\\n\\n/// @title Batched Loop Library\\n/// @notice Aids to perform a lengthy loop in seperate txs\\nlibrary BatchedLoop {\\n uint256 constant NULL = 0;\\n\\n struct Info {\\n uint256 progress; // of array element to resume the progress from\\n }\\n\\n /// @notice Resumes the loop from where it left of previously\\n /// @param loop: the loop object to resume (this is storage ref and val is mutated)\\n /// @param startAt: the index to start from\\n /// @param endBefore: the index to end at\\n /// @param batchSize: number of iterations to perform in this batch\\n /// @param execute: the function to execute for each iteration\\n /// @dev translates to: for(uint i = startAt; i < endBefore; i++) { execute(i); }\\n function iterate(\\n BatchedLoop.Info storage loop,\\n uint256 startAt,\\n uint256 endBefore,\\n uint256 batchSize,\\n function(uint256) execute\\n ) internal returns (bool completed) {\\n // resume the loop from the stored progress else use startAt\\n uint256 from = loop.progress;\\n if (from == NULL) from = startAt;\\n\\n // use endBefore if batchSize is zero, else calculate end index\\n uint256 to = batchSize == NULL ? endBefore : Math.min(from + batchSize, endBefore);\\n\\n // executes upto (to - 1)\\n while (from < to) {\\n execute(from);\\n from++;\\n }\\n\\n if (completed = (to == endBefore)) {\\n // if loop was completed then reset the progress\\n loop.progress = NULL;\\n } else {\\n // store the progress if partial execution of the loop\\n loop.progress = to;\\n }\\n }\\n\\n /// @notice Checks if the loop is in progress\\n /// @param loop: the loop object\\n /// @return true if the loop is in progress else false\\n function isInProgress(BatchedLoop.Info storage loop) internal view returns (bool) {\\n return loop.progress != NULL;\\n }\\n}\\n\",\"keccak256\":\"0xd3a852c38f34d78ba8a17f9d48f3b2f4410c779c4cd05db57b4563d5c6b391d2\",\"license\":\"MIT\"},\"contracts/libraries/Bisection.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\n/// @title Bisection Method\\n/// @notice https://en.wikipedia.org/wiki/Bisection_method\\nlibrary Bisection {\\n error SolutionOutOfBounds(uint256 y_target, uint160 x_lower, uint160 x_upper);\\n\\n /// @notice Finds the solution to the equation f(x) = y_target using the bisection method\\n /// @param f: strictly increasing function f: uint160 -> uint256\\n /// @param y_target: the target value of f(x)\\n /// @param x_lower: the lower bound for x\\n /// @param x_upper: the upper bound for x\\n /// @return x_target: the rounded down solution to the equation f(x) = y_target\\n function findSolution(\\n function(uint160) pure returns (uint256) f,\\n uint256 y_target,\\n uint160 x_lower,\\n uint160 x_upper\\n ) internal pure returns (uint160) {\\n // compute y at the bounds\\n uint256 y_lower = f(x_lower);\\n uint256 y_upper = f(x_upper);\\n\\n // if y is out of the bounds then revert\\n if (y_target < y_lower || y_target > y_upper) revert SolutionOutOfBounds(y_target, x_lower, x_upper);\\n\\n // bisect repeatedly until the solution is within an error of 1 unit\\n uint256 y_mid;\\n uint160 x_mid;\\n while (x_upper - x_lower > 1) {\\n x_mid = x_lower + (x_upper - x_lower) / 2;\\n y_mid = f(x_mid);\\n if (y_mid > y_target) {\\n x_upper = x_mid;\\n y_upper = y_mid;\\n } else {\\n x_lower = x_mid;\\n y_lower = y_mid;\\n }\\n }\\n\\n // at this point, x_upper - x_lower is either 0 or 1\\n // if it is 1 then check if x_upper is the solution, else return x_lower as the rounded down solution\\n return x_lower != x_upper && f(x_upper) == y_target ? x_upper : x_lower;\\n }\\n}\\n\",\"keccak256\":\"0xae30dfb5c8806a894fd086f494cd19bb7019c8bc865522b5ec407b7d71b8e4bc\",\"license\":\"MIT\"},\"contracts/libraries/Block.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ArbSys {\\n /**\\n * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)\\n * @return block number as int\\n */\\n function arbBlockNumber() external view returns (uint256);\\n}\\n\\n/// @title Library for getting block number for the current chain\\nlibrary Block {\\n /// @notice Get block number\\n /// @return block number as uint32\\n function number() internal view returns (uint32) {\\n uint256 chainId = block.chainid;\\n if (chainId == 42161 || chainId == 421611 || chainId == 421612) {\\n return uint32(ArbSys(address(100)).arbBlockNumber());\\n } else {\\n return uint32(block.number);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x19d3884d36aa0f25572b23843633a8b018509e37c7b75852b163a94cfc3aca4a\",\"license\":\"MIT\"},\"contracts/libraries/CollateralDeposit.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\n\\nimport { Protocol } from './Protocol.sol';\\nimport { AddressHelper } from './AddressHelper.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { Uint32L8ArrayLib } from './Uint32L8Array.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\n\\n/// @title Collateral deposit set functions\\nlibrary CollateralDeposit {\\n using AddressHelper for address;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n using Uint32L8ArrayLib for uint32[8];\\n\\n error InsufficientCollateralBalance();\\n\\n struct Set {\\n // Fixed length array of collateralId = collateralAddress.truncate()\\n // Supports upto 8 different collaterals in an account.\\n // Collision is possible, i.e. collateralAddress1.truncate() == collateralAddress2.truncate()\\n // However the possibility is 1/2**32, which is negligible.\\n // There are checks that prevent use of a different collateralAddress for a given collateralId.\\n // If there is a geniune collision, a wrapper for the ERC20 token can deployed such that\\n // there are no collisions with wrapper and the wrapped ERC20 can be used as collateral.\\n uint32[8] active; // array of collateralIds\\n mapping(uint32 => uint256) deposits; // collateralId => deposit amount\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n function getBalance(CollateralDeposit.Set storage set, uint32 collateralId) internal view returns (uint256) {\\n return set.deposits[collateralId];\\n }\\n\\n /// @notice Increase the deposit amount of a given collateralId\\n /// @param set CollateralDepositSet of the account\\n /// @param collateralId The collateralId of the collateral to increase the deposit amount of\\n /// @param amount The amount to increase the deposit amount of the collateral by\\n function increaseBalance(\\n CollateralDeposit.Set storage set,\\n uint32 collateralId,\\n uint256 amount\\n ) internal {\\n set.active.include(collateralId);\\n\\n set.deposits[collateralId] += amount;\\n }\\n\\n /// @notice Decrease the deposit amount of a given collateralId\\n /// @param set CollateralDepositSet of the account\\n /// @param collateralId The collateralId of the collateral to decrease the deposit amount of\\n /// @param amount The amount to decrease the deposit amount of the collateral by\\n function decreaseBalance(\\n CollateralDeposit.Set storage set,\\n uint32 collateralId,\\n uint256 amount\\n ) internal {\\n if (set.deposits[collateralId] < amount) revert InsufficientCollateralBalance();\\n set.deposits[collateralId] -= amount;\\n\\n if (set.deposits[collateralId] == 0) {\\n set.active.exclude(collateralId);\\n }\\n }\\n\\n /// @notice Get the market value of all the collateral deposits in settlementToken denomination\\n /// @param set CollateralDepositSet of the account\\n /// @param protocol Global protocol state\\n /// @return The market value of all the collateral deposits in settlementToken denomination\\n function marketValue(CollateralDeposit.Set storage set, Protocol.Info storage protocol)\\n internal\\n view\\n returns (int256)\\n {\\n int256 accountMarketValue;\\n for (uint8 i = 0; i < set.active.length; i++) {\\n uint32 collateralId = set.active[i];\\n\\n if (collateralId == 0) break;\\n IClearingHouseStructures.Collateral storage collateral = protocol.collaterals[collateralId];\\n\\n accountMarketValue += set.deposits[collateralId].toInt256().mulDiv(\\n collateral.settings.oracle.getTwapPriceX128(collateral.settings.twapDuration),\\n FixedPoint128.Q128\\n );\\n }\\n return accountMarketValue;\\n }\\n\\n /// @notice Get information about all the collateral deposits\\n /// @param set CollateralDepositSet of the account\\n /// @param protocol Global protocol state\\n /// @return collateralDeposits Information about all the collateral deposits\\n function getInfo(CollateralDeposit.Set storage set, Protocol.Info storage protocol)\\n internal\\n view\\n returns (IClearingHouseStructures.CollateralDepositView[] memory collateralDeposits)\\n {\\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\\n collateralDeposits = new IClearingHouseStructures.CollateralDepositView[](numberOfTokenPositions);\\n\\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\\n collateralDeposits[i].collateral = protocol.collaterals[set.active[i]].token;\\n collateralDeposits[i].balance = set.deposits[set.active[i]];\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa0444f3ae1a5555e1d31ab25d0df8e61d4760295c325ae63ca244efc72dede99\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/FundingPayment.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\n\\nimport { SafeCast } from './SafeCast.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\n\\n/// @title Funding payment functions\\n/// @notice Funding Payment Logic used to distribute the FP bill paid by traders among the LPs in the liquidity range\\nlibrary FundingPayment {\\n using FullMath for uint256;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n\\n struct Info {\\n // FR * P * dt\\n int256 sumAX128;\\n // trade token amount / liquidity\\n int256 sumBX128;\\n // sum(a * sumB)\\n int256 sumFpX128;\\n // time when state was last updated\\n uint48 timestampLast;\\n }\\n\\n event FundingPaymentStateUpdated(\\n FundingPayment.Info fundingPayment,\\n int256 fundingRateX128,\\n uint256 virtualPriceX128\\n );\\n\\n /// @notice Calculates the funding rate based on prices\\n /// @param realPriceX128 spot price of token\\n /// @param virtualPriceX128 futures price of token\\n function getFundingRate(uint256 realPriceX128, uint256 virtualPriceX128)\\n internal\\n pure\\n returns (int256 fundingRateX128)\\n {\\n int256 priceDeltaX128 = virtualPriceX128.toInt256() - realPriceX128.toInt256();\\n return priceDeltaX128.mulDiv(FixedPoint128.Q128, realPriceX128) / 1 days;\\n }\\n\\n /// @notice Used to update the state of the funding payment whenever a trade takes place\\n /// @param info pointer to the funding payment state\\n /// @param vTokenAmount trade token amount\\n /// @param liquidity active liquidity in the range during the trade (step)\\n /// @param blockTimestamp timestamp of current block\\n /// @param fundingRateX128 the constant funding rate to apply for the duration between timestampLast and blockTimestamp\\n /// @param virtualPriceX128 futures price of token\\n function update(\\n FundingPayment.Info storage info,\\n int256 vTokenAmount,\\n uint256 liquidity,\\n uint48 blockTimestamp,\\n int256 fundingRateX128,\\n uint256 virtualPriceX128\\n ) internal {\\n int256 a = nextAX128(info.timestampLast, blockTimestamp, fundingRateX128, virtualPriceX128);\\n info.sumFpX128 += a.mulDivRoundingDown(info.sumBX128, int256(FixedPoint128.Q128));\\n info.sumAX128 += a;\\n info.sumBX128 += vTokenAmount.mulDiv(int256(FixedPoint128.Q128), int256(liquidity));\\n info.timestampLast = blockTimestamp;\\n\\n emit FundingPaymentStateUpdated(info, fundingRateX128, virtualPriceX128);\\n }\\n\\n /// @notice Used to get the rate of funding payment for the duration between last trade and this trade\\n /// @dev Positive A value means at this duration, longs pay shorts. Negative means shorts pay longs.\\n /// @param timestampLast start timestamp of duration\\n /// @param blockTimestamp end timestamp of duration\\n /// @param virtualPriceX128 futures price of token\\n /// @param fundingRateX128 the constant funding rate to apply for the duration between timestampLast and blockTimestamp\\n /// @return aX128 value called \\\"a\\\" (see funding payment math documentation)\\n function nextAX128(\\n uint48 timestampLast,\\n uint48 blockTimestamp,\\n int256 fundingRateX128,\\n uint256 virtualPriceX128\\n ) internal pure returns (int256 aX128) {\\n return fundingRateX128.mulDiv(virtualPriceX128, FixedPoint128.Q128) * int48(blockTimestamp - timestampLast);\\n }\\n\\n function extrapolatedSumAX128(\\n int256 sumAX128,\\n uint48 timestampLast,\\n uint48 blockTimestamp,\\n int256 fundingRateX128,\\n uint256 virtualPriceX128\\n ) internal pure returns (int256) {\\n return sumAX128 + nextAX128(timestampLast, blockTimestamp, fundingRateX128, virtualPriceX128);\\n }\\n\\n /// @notice Extrapolates (updates) the value of sumFp by adding the missing component to it using sumAGlobalX128\\n /// @param sumAX128 sumA value that is recorded from global at some point in time\\n /// @param sumBX128 sumB value that is recorded from global at same point in time as sumA\\n /// @param sumFpX128 sumFp value that is recorded from global at same point in time as sumA and sumB\\n /// @param sumAGlobalX128 latest sumA value (taken from global), used to extrapolate the sumFp\\n function extrapolatedSumFpX128(\\n int256 sumAX128,\\n int256 sumBX128,\\n int256 sumFpX128,\\n int256 sumAGlobalX128\\n ) internal pure returns (int256) {\\n return sumFpX128 + sumBX128.mulDiv(sumAGlobalX128 - sumAX128, int256(FixedPoint128.Q128));\\n }\\n\\n /// @notice Positive bill is charged from LPs, Negative bill is rewarded to LPs\\n /// @param sumAX128 latest value of sumA (to be taken from global state)\\n /// @param sumFpInsideX128 latest value of sumFp inside range (to be computed using global state + tick state)\\n /// @param sumALastX128 value of sumA when LP updated their liquidity last time\\n /// @param sumBInsideLastX128 value of sumB inside range when LP updated their liquidity last time\\n /// @param sumFpInsideLastX128 value of sumFp inside range when LP updated their liquidity last time\\n /// @param liquidity amount of liquidity which was constant for LP in the time duration\\n /// @return amount of vQuote tokens that should be charged if positive\\n function bill(\\n int256 sumAX128,\\n int256 sumFpInsideX128,\\n int256 sumALastX128,\\n int256 sumBInsideLastX128,\\n int256 sumFpInsideLastX128,\\n uint256 liquidity\\n ) internal pure returns (int256) {\\n return\\n (sumFpInsideX128 - extrapolatedSumFpX128(sumALastX128, sumBInsideLastX128, sumFpInsideLastX128, sumAX128))\\n .mulDivRoundingDown(liquidity, FixedPoint128.Q128);\\n }\\n\\n /// @notice Positive bill is charged from Traders, Negative bill is rewarded to Traders\\n /// @param sumAX128 latest value of sumA (to be taken from global state)\\n /// @param sumALastX128 value of sumA when trader updated their netTraderPosition\\n /// @param netTraderPosition oken amount which should be constant for time duration since sumALastX128 was recorded\\n /// @return amount of vQuote tokens that should be charged if positive\\n function bill(\\n int256 sumAX128,\\n int256 sumALastX128,\\n int256 netTraderPosition\\n ) internal pure returns (int256) {\\n return netTraderPosition.mulDiv((sumAX128 - sumALastX128), int256(FixedPoint128.Q128));\\n }\\n}\\n\",\"keccak256\":\"0x7b189aa450af422d069760e170f6631fb48333e0664806aa5cb833a6bc68d339\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/LiquidityPosition.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { SqrtPriceMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/SqrtPriceMath.sol';\\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\nimport { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { PriceMath } from './PriceMath.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\\nimport { FundingPayment } from './FundingPayment.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\n\\n/// @title Liquidity position functions\\nlibrary LiquidityPosition {\\n using FullMath for uint256;\\n using PriceMath for uint160;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n using UniswapV3PoolHelper for IUniswapV3Pool;\\n\\n using LiquidityPosition for LiquidityPosition.Info;\\n using Protocol for Protocol.Info;\\n\\n struct Set {\\n // multiple per pool because it's non-fungible, allows for 4 billion LP positions lifetime\\n uint48[5] active;\\n // concat(tickLow,tickHigh)\\n mapping(uint48 => LiquidityPosition.Info) positions;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n struct Info {\\n //Extra boolean to check if it is limit order and uint to track limit price.\\n IClearingHouseEnums.LimitOrderType limitOrderType;\\n // the tick range of the position;\\n int24 tickLower;\\n int24 tickUpper;\\n // the liquidity of the position\\n uint128 liquidity;\\n int256 vTokenAmountIn;\\n // funding payment checkpoints\\n int256 sumALastX128;\\n int256 sumBInsideLastX128;\\n int256 sumFpInsideLastX128;\\n // fee growth inside\\n uint256 sumFeeInsideLastX128;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n error LP_AlreadyInitialized();\\n error LP_IneligibleLimitOrderRemoval();\\n\\n /// @notice denotes liquidity add/remove\\n /// @param accountId serial number of the account\\n /// @param poolId address of token whose position was taken\\n /// @param tickLower lower tick of the range updated\\n /// @param tickUpper upper tick of the range updated\\n /// @param liquidityDelta change in liquidity value\\n /// @param limitOrderType the type of range position\\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\\n /// @param vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\\n event LiquidityChanged(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n int128 liquidityDelta,\\n IClearingHouseEnums.LimitOrderType limitOrderType,\\n int256 vTokenAmountOut,\\n int256 vQuoteAmountOut,\\n uint160 sqrtPriceX96\\n );\\n\\n /// @param accountId serial number of the account\\n /// @param poolId address of token for which funding was paid\\n /// @param tickLower lower tick of the range for which funding was paid\\n /// @param tickUpper upper tick of the range for which funding was paid\\n /// @param amount amount of funding paid (negative) or received (positive)\\n /// @param sumALastX128 val of sum of the term A in funding payment math, when op took place\\n /// @param sumBInsideLastX128 val of sum of the term B in funding payment math, when op took place\\n /// @param sumFpInsideLastX128 val of sum of the term Fp in funding payment math, when op took place\\n /// @param sumFeeInsideLastX128 val of sum of the term Fee in wrapper, when op took place\\n event LiquidityPositionFundingPaymentRealized(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n int256 amount,\\n int256 sumALastX128,\\n int256 sumBInsideLastX128,\\n int256 sumFpInsideLastX128,\\n uint256 sumFeeInsideLastX128\\n );\\n\\n /// @notice denotes fee payment for a range / token position\\n /// @dev for a token position tickLower = tickUpper = 0\\n /// @param accountId serial number of the account\\n /// @param poolId address of token for which fee was paid\\n /// @param tickLower lower tick of the range for which fee was paid\\n /// @param tickUpper upper tick of the range for which fee was paid\\n /// @param amount amount of fee paid (negative) or received (positive)\\n event LiquidityPositionEarningsRealized(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n int256 amount\\n );\\n\\n /**\\n * Internal methods\\n */\\n\\n /// @notice initializes a new LiquidityPosition.Info struct\\n /// @dev Reverts if the position is already initialized\\n /// @param position storage pointer of the position to initialize\\n /// @param tickLower lower tick of the range\\n /// @param tickUpper upper tick of the range\\n function initialize(\\n LiquidityPosition.Info storage position,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal {\\n if (position.isInitialized()) {\\n revert LP_AlreadyInitialized();\\n }\\n\\n position.tickLower = tickLower;\\n position.tickUpper = tickUpper;\\n }\\n\\n /// @notice changes liquidity for a position, informs pool wrapper and does necessary bookkeeping\\n /// @param position storage ref of the position to update\\n /// @param accountId serial number of the account, used to emit event\\n /// @param poolId id of the pool for which position was updated\\n /// @param liquidityDelta change in liquidity value\\n /// @param balanceAdjustments memory ref to the balance adjustments struct\\n /// @param protocol ref to the protocol state\\n function liquidityChange(\\n LiquidityPosition.Info storage position,\\n uint256 accountId,\\n uint32 poolId,\\n int128 liquidityDelta,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n int256 vTokenPrincipal;\\n int256 vQuotePrincipal;\\n\\n IVPoolWrapper wrapper = protocol.vPoolWrapper(poolId);\\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside;\\n\\n // calls wrapper to mint/burn liquidity\\n if (liquidityDelta > 0) {\\n uint256 vTokenPrincipal_;\\n uint256 vQuotePrincipal_;\\n (vTokenPrincipal_, vQuotePrincipal_, wrapperValuesInside) = wrapper.mint(\\n position.tickLower,\\n position.tickUpper,\\n uint128(liquidityDelta)\\n );\\n vTokenPrincipal = vTokenPrincipal_.toInt256();\\n vQuotePrincipal = vQuotePrincipal_.toInt256();\\n } else {\\n uint256 vTokenPrincipal_;\\n uint256 vQuotePrincipal_;\\n (vTokenPrincipal_, vQuotePrincipal_, wrapperValuesInside) = wrapper.burn(\\n position.tickLower,\\n position.tickUpper,\\n uint128(-liquidityDelta)\\n );\\n vTokenPrincipal = -vTokenPrincipal_.toInt256();\\n vQuotePrincipal = -vQuotePrincipal_.toInt256();\\n }\\n\\n // calculate funding payment and liquidity fees then update checkpoints\\n position.update(accountId, poolId, wrapperValuesInside, balanceAdjustments);\\n\\n // adjust in the token acounts\\n balanceAdjustments.vQuoteIncrease -= vQuotePrincipal;\\n balanceAdjustments.vTokenIncrease -= vTokenPrincipal;\\n\\n // emit the event\\n uint160 sqrtPriceCurrent = protocol.vPool(poolId).sqrtPriceCurrent();\\n emitLiquidityChangeEvent(\\n position,\\n accountId,\\n poolId,\\n liquidityDelta,\\n sqrtPriceCurrent,\\n -vTokenPrincipal,\\n -vQuotePrincipal\\n );\\n\\n // update trader position increase\\n int256 vTokenAmountCurrent;\\n {\\n (vTokenAmountCurrent, ) = position.vTokenAmountsInRange(sqrtPriceCurrent, false);\\n balanceAdjustments.traderPositionIncrease += (vTokenAmountCurrent - position.vTokenAmountIn);\\n }\\n\\n uint128 liquidityNew = position.liquidity;\\n if (liquidityDelta > 0) {\\n liquidityNew += uint128(liquidityDelta);\\n } else if (liquidityDelta < 0) {\\n liquidityNew -= uint128(-liquidityDelta);\\n }\\n\\n if (liquidityNew != 0) {\\n // update state\\n position.liquidity = liquidityNew;\\n position.vTokenAmountIn = vTokenAmountCurrent + vTokenPrincipal;\\n } else {\\n // clear all the state\\n position.liquidity = 0;\\n position.vTokenAmountIn = 0;\\n position.sumALastX128 = 0;\\n position.sumBInsideLastX128 = 0;\\n position.sumFpInsideLastX128 = 0;\\n position.sumFeeInsideLastX128 = 0;\\n }\\n }\\n\\n /// @notice updates the position with latest checkpoints, and realises fees and fp\\n /// @dev fees and funding payment are not immediately adjusted in token balance state,\\n /// balanceAdjustments struct is used to pass the necessary values to caller.\\n /// @param position storage ref of the position to update\\n /// @param accountId serial number of the account, used to emit event\\n /// @param poolId id of the pool for which position was updated\\n /// @param wrapperValuesInside range checkpoint values from the wrapper\\n /// @param balanceAdjustments memory ref to the balance adjustments struct\\n function update(\\n LiquidityPosition.Info storage position,\\n uint256 accountId,\\n uint32 poolId,\\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments\\n ) internal {\\n int256 fundingPayment = position.unrealizedFundingPayment(\\n wrapperValuesInside.sumAX128,\\n wrapperValuesInside.sumFpInsideX128\\n );\\n balanceAdjustments.vQuoteIncrease += fundingPayment;\\n\\n int256 unrealizedLiquidityFee = position.unrealizedFees(wrapperValuesInside.sumFeeInsideX128).toInt256();\\n balanceAdjustments.vQuoteIncrease += unrealizedLiquidityFee;\\n\\n // updating checkpoints\\n position.sumALastX128 = wrapperValuesInside.sumAX128;\\n position.sumBInsideLastX128 = wrapperValuesInside.sumBInsideX128;\\n position.sumFpInsideLastX128 = wrapperValuesInside.sumFpInsideX128;\\n position.sumFeeInsideLastX128 = wrapperValuesInside.sumFeeInsideX128;\\n\\n emit LiquidityPositionFundingPaymentRealized(\\n accountId,\\n poolId,\\n position.tickLower,\\n position.tickUpper,\\n fundingPayment,\\n wrapperValuesInside.sumAX128,\\n wrapperValuesInside.sumBInsideX128,\\n wrapperValuesInside.sumFpInsideX128,\\n wrapperValuesInside.sumFeeInsideX128\\n );\\n\\n emit LiquidityPositionEarningsRealized(\\n accountId,\\n poolId,\\n position.tickLower,\\n position.tickUpper,\\n unrealizedLiquidityFee\\n );\\n }\\n\\n /**\\n * Internal view methods\\n */\\n\\n /// @notice ensures that limit order removal is valid, else reverts\\n /// @param info storage ref of the position to check\\n /// @param currentTick current tick in the pool\\n function checkValidLimitOrderRemoval(LiquidityPosition.Info storage info, int24 currentTick) internal view {\\n if (\\n !((currentTick >= info.tickUpper &&\\n info.limitOrderType == IClearingHouseEnums.LimitOrderType.UPPER_LIMIT) ||\\n (currentTick <= info.tickLower &&\\n info.limitOrderType == IClearingHouseEnums.LimitOrderType.LOWER_LIMIT))\\n ) {\\n revert LP_IneligibleLimitOrderRemoval();\\n }\\n }\\n\\n /// @notice checks if the position is initialized\\n /// @param info storage ref of the position to check\\n /// @return true if the position is initialized\\n function isInitialized(LiquidityPosition.Info storage info) internal view returns (bool) {\\n return info.tickLower != 0 || info.tickUpper != 0;\\n }\\n\\n /// @notice calculates the long side risk for the position\\n /// @param position storage ref of the position to check\\n /// @param valuationSqrtPriceX96 valuation sqrt price in x96\\n /// @return long side risk\\n function longSideRisk(LiquidityPosition.Info storage position, uint160 valuationSqrtPriceX96)\\n internal\\n view\\n returns (uint256)\\n {\\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\\n uint256 longPositionExecutionPriceX128;\\n {\\n uint160 sqrtPriceUpperMinX96 = valuationSqrtPriceX96 <= sqrtPriceUpperX96\\n ? valuationSqrtPriceX96\\n : sqrtPriceUpperX96;\\n uint160 sqrtPriceLowerMinX96 = valuationSqrtPriceX96 <= sqrtPriceLowerX96\\n ? valuationSqrtPriceX96\\n : sqrtPriceLowerX96;\\n longPositionExecutionPriceX128 = uint256(sqrtPriceLowerMinX96).mulDiv(sqrtPriceUpperMinX96, 1 << 64);\\n }\\n\\n uint256 maxNetLongPosition;\\n {\\n uint256 maxLongTokens = SqrtPriceMath.getAmount0Delta(\\n sqrtPriceLowerX96,\\n sqrtPriceUpperX96,\\n position.liquidity,\\n true\\n );\\n //\\n if (position.vTokenAmountIn >= 0) {\\n //maxLongTokens in range should always be >= amount that got added to range, equality occurs when range was added at pCurrent = pHigh\\n assert(maxLongTokens >= uint256(position.vTokenAmountIn));\\n maxNetLongPosition = maxLongTokens - uint256(position.vTokenAmountIn);\\n } else maxNetLongPosition = maxLongTokens + uint256(-1 * position.vTokenAmountIn);\\n }\\n\\n return maxNetLongPosition.mulDiv(longPositionExecutionPriceX128, FixedPoint128.Q128);\\n }\\n\\n /// @notice calculates the market value for the position using a provided price\\n /// @param position storage ref of the position to check\\n /// @param valuationSqrtPriceX96 valuation sqrt price to be used\\n /// @param wrapper address of the pool wrapper\\n /// @return marketValue_ the market value of the position\\n function marketValue(\\n LiquidityPosition.Info storage position,\\n uint160 valuationSqrtPriceX96,\\n IVPoolWrapper wrapper\\n ) internal view returns (int256 marketValue_) {\\n {\\n (int256 vTokenAmount, int256 vQuoteAmount) = position.vTokenAmountsInRange(valuationSqrtPriceX96, false);\\n uint256 priceX128 = valuationSqrtPriceX96.toPriceX128();\\n marketValue_ = vTokenAmount.mulDiv(priceX128, FixedPoint128.Q128) + vQuoteAmount;\\n }\\n // adding fees\\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside = wrapper.getExtrapolatedValuesInside(\\n position.tickLower,\\n position.tickUpper\\n );\\n marketValue_ += position.unrealizedFees(wrapperValuesInside.sumFeeInsideX128).toInt256();\\n marketValue_ += position.unrealizedFundingPayment(\\n wrapperValuesInside.sumAX128,\\n wrapperValuesInside.sumFpInsideX128\\n );\\n }\\n\\n /// @notice calculates the max net position for the position\\n /// @param position storage ref of the position to check\\n /// @return maxNetPosition the max net position of the position\\n function maxNetPosition(LiquidityPosition.Info storage position) internal view returns (uint256) {\\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\\n\\n if (position.vTokenAmountIn >= 0)\\n return\\n SqrtPriceMath.getAmount0Delta(sqrtPriceLowerX96, sqrtPriceUpperX96, position.liquidity, true) -\\n uint256(position.vTokenAmountIn);\\n else\\n return\\n SqrtPriceMath.getAmount0Delta(sqrtPriceLowerX96, sqrtPriceUpperX96, position.liquidity, true) +\\n uint256(-1 * position.vTokenAmountIn);\\n }\\n\\n /// @notice calculates the current net position for the position\\n /// @param position storage ref of the position to check\\n /// @param sqrtPriceCurrent the current sqrt price, used to calculate net position\\n /// @return netTokenPosition the current net position of the position\\n function netPosition(LiquidityPosition.Info storage position, uint160 sqrtPriceCurrent)\\n internal\\n view\\n returns (int256 netTokenPosition)\\n {\\n int256 vTokenAmountCurrent;\\n (vTokenAmountCurrent, ) = position.vTokenAmountsInRange(sqrtPriceCurrent, false);\\n netTokenPosition = (vTokenAmountCurrent - position.vTokenAmountIn);\\n }\\n\\n /// @notice calculates the current virtual token amounts for the position\\n /// @param position storage ref of the position to check\\n /// @param sqrtPriceCurrent the current sqrt price, used to calculate virtual token amounts\\n /// @param roundUp whether to round up the token amounts, purpose to charge user more and give less\\n /// @return vTokenAmount the current vToken amount\\n /// @return vQuoteAmount the current vQuote amount\\n function vTokenAmountsInRange(\\n LiquidityPosition.Info storage position,\\n uint160 sqrtPriceCurrent,\\n bool roundUp\\n ) internal view returns (int256 vTokenAmount, int256 vQuoteAmount) {\\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\\n\\n // If price is outside the range, then consider it at the ends\\n // for calculation of amounts\\n uint160 sqrtPriceMiddleX96 = sqrtPriceCurrent;\\n if (sqrtPriceCurrent < sqrtPriceLowerX96) {\\n sqrtPriceMiddleX96 = sqrtPriceLowerX96;\\n } else if (sqrtPriceCurrent > sqrtPriceUpperX96) {\\n sqrtPriceMiddleX96 = sqrtPriceUpperX96;\\n }\\n\\n vTokenAmount = SqrtPriceMath\\n .getAmount0Delta(sqrtPriceMiddleX96, sqrtPriceUpperX96, position.liquidity, roundUp)\\n .toInt256();\\n vQuoteAmount = SqrtPriceMath\\n .getAmount1Delta(sqrtPriceLowerX96, sqrtPriceMiddleX96, position.liquidity, roundUp)\\n .toInt256();\\n }\\n\\n /// @notice returns vQuoteIncrease due to unrealised funding payment for the liquidity position (+ve means receiving and -ve means giving)\\n /// @param position storage ref of the position to check\\n /// @param sumAX128 the sumA value from the pool wrapper\\n /// @param sumFpInsideX128 the sumFp in the position's range from the pool wrapper\\n /// @return vQuoteIncrease the amount of vQuote that should be added to the account's vQuote balance\\n function unrealizedFundingPayment(\\n LiquidityPosition.Info storage position,\\n int256 sumAX128,\\n int256 sumFpInsideX128\\n ) internal view returns (int256 vQuoteIncrease) {\\n // subtract the bill from the account's vQuote balance\\n vQuoteIncrease = -FundingPayment.bill(\\n sumAX128,\\n sumFpInsideX128,\\n position.sumALastX128,\\n position.sumBInsideLastX128,\\n position.sumFpInsideLastX128,\\n position.liquidity\\n );\\n }\\n\\n /// @notice calculates the unrealised lp fees for the position\\n /// @param position storage ref of the position to check\\n /// @param sumFeeInsideX128 the global sumFee in the position's range from the pool wrapper\\n /// @return vQuoteIncrease the amount of vQuote that should be added to the account's vQuote balance\\n function unrealizedFees(LiquidityPosition.Info storage position, uint256 sumFeeInsideX128)\\n internal\\n view\\n returns (uint256 vQuoteIncrease)\\n {\\n vQuoteIncrease = (sumFeeInsideX128 - position.sumFeeInsideLastX128).mulDiv(\\n position.liquidity,\\n FixedPoint128.Q128\\n );\\n }\\n\\n function emitLiquidityChangeEvent(\\n LiquidityPosition.Info storage position,\\n uint256 accountId,\\n uint32 poolId,\\n int128 liquidityDelta,\\n uint160 sqrtPriceX96,\\n int256 vTokenAmountOut,\\n int256 vQuoteAmountOut\\n ) internal {\\n emit LiquidityChanged(\\n accountId,\\n poolId,\\n position.tickLower,\\n position.tickUpper,\\n liquidityDelta,\\n position.limitOrderType,\\n vTokenAmountOut,\\n vQuoteAmountOut,\\n sqrtPriceX96\\n );\\n }\\n}\\n\",\"keccak256\":\"0xdd835fed27adf6c4168843bbfa7074d29fd5b0cc25cee891b20bf353b18e985a\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/LiquidityPositionSet.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { LiquidityPosition } from './LiquidityPosition.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { Uint48Lib } from './Uint48.sol';\\nimport { Uint48L5ArrayLib } from './Uint48L5Array.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\n\\n/// @title Liquidity position set functions\\nlibrary LiquidityPositionSet {\\n using LiquidityPosition for LiquidityPosition.Info;\\n using LiquidityPositionSet for LiquidityPosition.Set;\\n using Protocol for Protocol.Info;\\n using Uint48Lib for int24;\\n using Uint48Lib for uint48;\\n using Uint48L5ArrayLib for uint48[5];\\n\\n error LPS_IllegalTicks(int24 tickLower, int24 tickUpper);\\n error LPS_DeactivationFailed(int24 tickLower, int24 tickUpper, uint256 liquidity);\\n error LPS_InactiveRange();\\n\\n /// @notice denotes token position change due to liquidity add/remove\\n /// @param accountId serial number of the account\\n /// @param poolId address of token whose position was taken\\n /// @param tickLower lower tick of the range updated\\n /// @param tickUpper upper tick of the range updated\\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\\n event TokenPositionChangedDueToLiquidityChanged(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n int256 vTokenAmountOut\\n );\\n\\n /**\\n * Internal methods\\n */\\n\\n /// @notice activates a position by initializing it and adding it to the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param tickLower lower tick of the range to be activated\\n /// @param tickUpper upper tick of the range to be activated\\n /// @return position storage ref of the activated position\\n function activate(\\n LiquidityPosition.Set storage set,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal returns (LiquidityPosition.Info storage position) {\\n if (tickLower > tickUpper) {\\n revert LPS_IllegalTicks(tickLower, tickUpper);\\n }\\n\\n uint48 positionId;\\n set.active.include(positionId = tickLower.concat(tickUpper));\\n position = set.positions[positionId];\\n\\n if (!position.isInitialized()) {\\n position.initialize(tickLower, tickUpper);\\n }\\n }\\n\\n /// @notice deactivates a position by removing it from the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param position storage ref to the position to be deactivated\\n function deactivate(LiquidityPosition.Set storage set, LiquidityPosition.Info storage position) internal {\\n if (position.liquidity != 0) {\\n revert LPS_DeactivationFailed(position.tickLower, position.tickUpper, position.liquidity);\\n }\\n\\n set.active.exclude(position.tickLower.concat(position.tickUpper));\\n }\\n\\n /// @notice changes liquidity of a position in the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param liquidityChangeParams parameters of the liquidity change\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function liquidityChange(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n LiquidityPosition.Info storage position = set.activate(\\n liquidityChangeParams.tickLower,\\n liquidityChangeParams.tickUpper\\n );\\n\\n position.limitOrderType = liquidityChangeParams.limitOrderType;\\n\\n set.liquidityChange(\\n accountId,\\n poolId,\\n position,\\n liquidityChangeParams.liquidityDelta,\\n balanceAdjustments,\\n protocol\\n );\\n }\\n\\n /// @notice changes liquidity of a position in the set\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param position storage ref to the position to be changed\\n /// @param liquidityDelta amount of liquidity to be added or removed\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function liquidityChange(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n LiquidityPosition.Info storage position,\\n int128 liquidityDelta,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n position.liquidityChange(accountId, poolId, liquidityDelta, balanceAdjustments, protocol);\\n\\n emit TokenPositionChangedDueToLiquidityChanged(\\n accountId,\\n poolId,\\n position.tickLower,\\n position.tickUpper,\\n balanceAdjustments.vTokenIncrease\\n );\\n\\n if (position.liquidity == 0) {\\n set.deactivate(position);\\n }\\n }\\n\\n /// @notice removes liquidity from a position in the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param position storage ref to the position to be closed\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function closeLiquidityPosition(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n LiquidityPosition.Info storage position,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n set.liquidityChange(accountId, poolId, position, -int128(position.liquidity), balanceAdjustments, protocol);\\n }\\n\\n /// @notice removes liquidity from a position in the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param currentTick current tick of the pool\\n /// @param tickLower lower tick of the range to be closed\\n /// @param tickUpper upper tick of the range to be closed\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function removeLimitOrder(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n int24 currentTick,\\n int24 tickLower,\\n int24 tickUpper,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n LiquidityPosition.Info storage position = set.getLiquidityPosition(tickLower, tickUpper);\\n position.checkValidLimitOrderRemoval(currentTick);\\n set.closeLiquidityPosition(accountId, poolId, position, balanceAdjustments, protocol);\\n }\\n\\n /// @notice removes liquidity from all the positions in the set\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vToken\\n /// @param balanceAdjustments adjustments to made to the account's balance later\\n /// @param protocol ref to the state of the protocol\\n function closeAllLiquidityPositions(\\n LiquidityPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n Protocol.Info storage protocol\\n ) internal {\\n LiquidityPosition.Info storage position;\\n\\n while (set.active[0] != 0) {\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustmentsCurrent;\\n\\n position = set.positions[set.active[0]];\\n\\n set.closeLiquidityPosition(accountId, poolId, position, balanceAdjustmentsCurrent, protocol);\\n\\n balanceAdjustments.vQuoteIncrease += balanceAdjustmentsCurrent.vQuoteIncrease;\\n balanceAdjustments.vTokenIncrease += balanceAdjustmentsCurrent.vTokenIncrease;\\n balanceAdjustments.traderPositionIncrease += balanceAdjustmentsCurrent.traderPositionIncrease;\\n }\\n }\\n\\n /**\\n * Internal view methods\\n */\\n\\n /// @notice gets the liquidity position of a tick range\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param tickLower lower tick of the range to be closed\\n /// @param tickUpper upper tick of the range to be closed\\n /// @return position liquidity position of the tick range\\n function getLiquidityPosition(\\n LiquidityPosition.Set storage set,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal view returns (LiquidityPosition.Info storage position) {\\n if (tickLower > tickUpper) {\\n revert LPS_IllegalTicks(tickLower, tickUpper);\\n }\\n\\n uint48 positionId = Uint48Lib.concat(tickLower, tickUpper);\\n position = set.positions[positionId];\\n\\n if (!position.isInitialized()) revert LPS_InactiveRange();\\n return position;\\n }\\n\\n /// @notice gets information about all the liquidity position\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @return liquidityPositions Information about all the liquidity position for the pool\\n function getInfo(LiquidityPosition.Set storage set)\\n internal\\n view\\n returns (IClearingHouseStructures.LiquidityPositionView[] memory liquidityPositions)\\n {\\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\\n liquidityPositions = new IClearingHouseStructures.LiquidityPositionView[](numberOfTokenPositions);\\n\\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\\n liquidityPositions[i].limitOrderType = set.positions[set.active[i]].limitOrderType;\\n liquidityPositions[i].tickLower = set.positions[set.active[i]].tickLower;\\n liquidityPositions[i].tickUpper = set.positions[set.active[i]].tickUpper;\\n liquidityPositions[i].liquidity = set.positions[set.active[i]].liquidity;\\n liquidityPositions[i].vTokenAmountIn = set.positions[set.active[i]].vTokenAmountIn;\\n liquidityPositions[i].sumALastX128 = set.positions[set.active[i]].sumALastX128;\\n liquidityPositions[i].sumBInsideLastX128 = set.positions[set.active[i]].sumBInsideLastX128;\\n liquidityPositions[i].sumFpInsideLastX128 = set.positions[set.active[i]].sumFpInsideLastX128;\\n liquidityPositions[i].sumFeeInsideLastX128 = set.positions[set.active[i]].sumFeeInsideLastX128;\\n }\\n }\\n\\n /// @notice gets the net position due to all the liquidity positions\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param sqrtPriceCurrent current sqrt price of the pool\\n /// @return netPosition due to all the liquidity positions\\n function getNetPosition(LiquidityPosition.Set storage set, uint160 sqrtPriceCurrent)\\n internal\\n view\\n returns (int256 netPosition)\\n {\\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\\n\\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\\n netPosition += set.positions[set.active[i]].netPosition(sqrtPriceCurrent);\\n }\\n }\\n\\n /// @notice checks whether the liquidity position set is empty\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @return true if the liquidity position set is empty\\n function isEmpty(LiquidityPosition.Set storage set) internal view returns (bool) {\\n return set.active.isEmpty();\\n }\\n\\n /// @notice checks whether for given ticks, a liquidity position is active\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param tickLower lower tick of the range\\n /// @param tickUpper upper tick of the range\\n /// @return true if the liquidity position is active\\n function isPositionActive(\\n LiquidityPosition.Set storage set,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal view returns (bool) {\\n return set.active.exists(tickLower.concat(tickUpper));\\n }\\n\\n /// @notice gets the total long side risk for all the active liquidity positions\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param valuationPriceX96 price used to value the vToken asset\\n /// @return risk the net long side risk for all the active liquidity positions\\n function longSideRisk(LiquidityPosition.Set storage set, uint160 valuationPriceX96)\\n internal\\n view\\n returns (uint256 risk)\\n {\\n for (uint256 i = 0; i < set.active.length; i++) {\\n uint48 id = set.active[i];\\n if (id == 0) break;\\n risk += set.positions[id].longSideRisk(valuationPriceX96);\\n }\\n }\\n\\n /// @notice gets the total market value of all the active liquidity positions\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @param sqrtPriceCurrent price used to value the vToken asset\\n /// @param poolId the id of the pool\\n /// @param protocol ref to the state of the protocol\\n /// @return marketValue_ the total market value of all the active liquidity positions\\n function marketValue(\\n LiquidityPosition.Set storage set,\\n uint160 sqrtPriceCurrent,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 marketValue_) {\\n marketValue_ = set.marketValue(sqrtPriceCurrent, protocol.vPoolWrapper(poolId));\\n }\\n\\n /// @notice Get the total market value of all active liquidity positions in the set.\\n /// @param set: Collection of active liquidity positions\\n /// @param sqrtPriceCurrent: Current price of the virtual asset\\n /// @param wrapper: address of the wrapper contract, passed once to avoid multiple sloads for wrapper\\n function marketValue(\\n LiquidityPosition.Set storage set,\\n uint160 sqrtPriceCurrent,\\n IVPoolWrapper wrapper\\n ) internal view returns (int256 marketValue_) {\\n for (uint256 i = 0; i < set.active.length; i++) {\\n uint48 id = set.active[i];\\n if (id == 0) break;\\n marketValue_ += set.positions[id].marketValue(sqrtPriceCurrent, wrapper);\\n }\\n }\\n\\n /// @notice gets the max net position possible due to all the liquidity positions\\n /// @param set storage ref to the account's set of liquidity positions of a pool\\n /// @return risk the max net position possible due to all the liquidity positions\\n function maxNetPosition(LiquidityPosition.Set storage set) internal view returns (uint256 risk) {\\n for (uint256 i = 0; i < set.active.length; i++) {\\n uint48 id = set.active[i];\\n if (id == 0) break;\\n risk += set.positions[id].maxNetPosition();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x20552c4941db1f89a751daa063774d5daa0a8dbad241e43bf1abf91f6e653d5c\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/PriceMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';\\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\\n\\nimport { Bisection } from './Bisection.sol';\\n\\n/// @title Price math functions\\nlibrary PriceMath {\\n using FullMath for uint256;\\n\\n error IllegalSqrtPrice(uint160 sqrtPriceX96);\\n\\n /// @notice Computes the square of a sqrtPriceX96 value\\n /// @param sqrtPriceX96: the square root of the input price in Q96 format\\n /// @return priceX128 : input price in Q128 format\\n function toPriceX128(uint160 sqrtPriceX96) internal pure returns (uint256 priceX128) {\\n if (sqrtPriceX96 < TickMath.MIN_SQRT_RATIO || sqrtPriceX96 >= TickMath.MAX_SQRT_RATIO) {\\n revert IllegalSqrtPrice(sqrtPriceX96);\\n }\\n\\n priceX128 = _toPriceX128(sqrtPriceX96);\\n }\\n\\n /// @notice computes the square of a sqrtPriceX96 value\\n /// @param sqrtPriceX96: input price in Q128 format\\n function _toPriceX128(uint160 sqrtPriceX96) private pure returns (uint256 priceX128) {\\n priceX128 = uint256(sqrtPriceX96).mulDiv(sqrtPriceX96, 1 << 64);\\n }\\n\\n /// @notice computes the square root of a priceX128 value\\n /// @param priceX128: input price in Q128 format\\n /// @return sqrtPriceX96 : the square root of the input price in Q96 format\\n function toSqrtPriceX96(uint256 priceX128) internal pure returns (uint160 sqrtPriceX96) {\\n // Uses bisection method to find solution to the equation toPriceX128(x) = priceX128\\n sqrtPriceX96 = Bisection.findSolution(\\n _toPriceX128,\\n priceX128,\\n /// @dev sqrtPriceX96 is always bounded by MIN_SQRT_RATIO and MAX_SQRT_RATIO.\\n /// If solution falls outside of these bounds, findSolution method reverts\\n TickMath.MIN_SQRT_RATIO,\\n TickMath.MAX_SQRT_RATIO - 1\\n );\\n }\\n}\\n\",\"keccak256\":\"0x88bb3e3cb05a8474c5e69c26e2c29bf382a82a4d460f79674ae407114463c3b7\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/Protocol.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { Math } from '@openzeppelin/contracts/utils/math/Math.sol';\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IVQuote } from '../interfaces/IVQuote.sol';\\nimport { IVToken } from '../interfaces/IVToken.sol';\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\n\\nimport { PriceMath } from './PriceMath.sol';\\nimport { SafeCast } from './SafeCast.sol';\\nimport { SignedMath } from './SignedMath.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\\nimport { Block } from './Block.sol';\\nimport { SafeCast } from './SafeCast.sol';\\n\\n/// @title Protocol storage functions\\n/// @dev This is used as main storage interface containing protocol info\\nlibrary Protocol {\\n using FullMath for uint256;\\n using PriceMath for uint160;\\n using PriceMath for uint256;\\n using SignedMath for int256;\\n using SignedFullMath for int256;\\n using SafeCast for uint256;\\n using UniswapV3PoolHelper for IUniswapV3Pool;\\n using SafeCast for uint256;\\n\\n using Protocol for Protocol.Info;\\n\\n struct PriceCache {\\n uint32 updateBlockNumber;\\n uint224 virtualPriceX128;\\n uint224 realPriceX128;\\n bool isDeviationBreached;\\n }\\n struct Info {\\n // poolId => PoolInfo\\n mapping(uint32 => IClearingHouseStructures.Pool) pools;\\n // collateralId => CollateralInfo\\n mapping(uint32 => IClearingHouseStructures.Collateral) collaterals;\\n // iterable and increasing list of pools (used for admin functions)\\n uint32[] poolIds;\\n // settlement token (default collateral)\\n IERC20 settlementToken;\\n // virtual quote token (sort of fake USDC), is always token1 in uniswap pools\\n IVQuote vQuote;\\n // accounting settings\\n IClearingHouseStructures.LiquidationParams liquidationParams;\\n uint256 minRequiredMargin;\\n uint256 removeLimitOrderFee;\\n uint256 minimumOrderNotional;\\n // price cache\\n mapping(uint32 => PriceCache) priceCache;\\n // reserved for adding slots in future\\n uint256[100] _emptySlots;\\n }\\n\\n function updatePoolPriceCache(Protocol.Info storage protocol, uint32 poolId) internal {\\n uint32 blockNumber = Block.number();\\n\\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\\n if (poolPriceCache.updateBlockNumber == blockNumber) {\\n return;\\n }\\n\\n uint256 realPriceX128 = protocol.getRealTwapPriceX128(poolId);\\n uint256 virtualPriceX128 = protocol.getVirtualTwapPriceX128(poolId);\\n\\n // In case the price is breaching the Q224 limit, we do not cache it\\n uint256 Q224 = 1 << 224;\\n if (realPriceX128 >= Q224 || virtualPriceX128 >= Q224) {\\n return;\\n }\\n\\n uint16 maxDeviationBps = protocol.pools[poolId].settings.maxVirtualPriceDeviationRatioBps;\\n if (\\n // if virtual price is too off from real price then screw that, we'll just use real price\\n (int256(realPriceX128) - int256(virtualPriceX128)).absUint() > realPriceX128.mulDiv(maxDeviationBps, 1e4)\\n ) {\\n poolPriceCache.isDeviationBreached = true;\\n } else {\\n poolPriceCache.isDeviationBreached = false;\\n }\\n poolPriceCache.realPriceX128 = realPriceX128.toUint224();\\n poolPriceCache.virtualPriceX128 = virtualPriceX128.toUint224();\\n poolPriceCache.updateBlockNumber = blockNumber;\\n }\\n\\n /// @notice gets the uniswap v3 pool address for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return UniswapV3Pool contract object\\n function vPool(Protocol.Info storage protocol, uint32 poolId) internal view returns (IUniswapV3Pool) {\\n return protocol.pools[poolId].vPool;\\n }\\n\\n /// @notice gets the wrapper address for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return VPoolWrapper contract object\\n function vPoolWrapper(Protocol.Info storage protocol, uint32 poolId) internal view returns (IVPoolWrapper) {\\n return protocol.pools[poolId].vPoolWrapper;\\n }\\n\\n /// @notice gets the virtual twap sqrt price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return sqrtPriceX96 virtual twap sqrt price\\n function getVirtualTwapSqrtPriceX96(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint160 sqrtPriceX96)\\n {\\n IClearingHouseStructures.Pool storage pool = protocol.pools[poolId];\\n return pool.vPool.twapSqrtPrice(pool.settings.twapDuration);\\n }\\n\\n /// @notice gets the virtual current sqrt price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return sqrtPriceX96 virtual current sqrt price\\n function getVirtualCurrentSqrtPriceX96(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint160 sqrtPriceX96)\\n {\\n return protocol.pools[poolId].vPool.sqrtPriceCurrent();\\n }\\n\\n /// @notice gets the virtual current tick for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return tick virtual current tick\\n function getVirtualCurrentTick(Protocol.Info storage protocol, uint32 poolId) internal view returns (int24 tick) {\\n return protocol.pools[poolId].vPool.tickCurrent();\\n }\\n\\n /// @notice gets the virtual twap price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return priceX128 virtual twap price\\n function getVirtualTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n return protocol.getVirtualTwapSqrtPriceX96(poolId).toPriceX128();\\n }\\n\\n /// @notice gets the virtual current price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return priceX128 virtual current price\\n function getVirtualCurrentPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n return protocol.getVirtualCurrentSqrtPriceX96(poolId).toPriceX128();\\n }\\n\\n /// @notice gets the real twap price for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return priceX128 virtual twap price\\n function getRealTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n IClearingHouseStructures.Pool storage pool = protocol.pools[poolId];\\n return pool.settings.oracle.getTwapPriceX128(pool.settings.twapDuration);\\n }\\n\\n /// @notice gets the twap prices with deviation check for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return realPriceX128 the real price\\n /// @return virtualPriceX128 the virtual price if under deviation else real price\\n function getTwapPricesWithDeviationCheck(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 realPriceX128, uint256 virtualPriceX128)\\n {\\n realPriceX128 = protocol.getRealTwapPriceX128(poolId);\\n virtualPriceX128 = protocol.getVirtualTwapPriceX128(poolId);\\n\\n uint16 maxDeviationBps = protocol.pools[poolId].settings.maxVirtualPriceDeviationRatioBps;\\n uint256 priceDeltaX128 = realPriceX128 > virtualPriceX128\\n ? realPriceX128 - virtualPriceX128\\n : virtualPriceX128 - realPriceX128;\\n if (priceDeltaX128 > realPriceX128.mulDiv(maxDeviationBps, 1e4)) {\\n // if virtual price is too off from real price then screw that, we'll just use real price\\n virtualPriceX128 = realPriceX128;\\n }\\n return (realPriceX128, virtualPriceX128);\\n }\\n\\n function getCachedVirtualTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n uint32 blockNumber = Block.number();\\n\\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\\n if (poolPriceCache.updateBlockNumber == blockNumber) {\\n return poolPriceCache.virtualPriceX128;\\n } else {\\n return protocol.getVirtualTwapPriceX128(poolId);\\n }\\n }\\n\\n function getCachedTwapPricesWithDeviationCheck(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 realPriceX128, uint256 virtualPriceX128)\\n {\\n uint32 blockNumber = Block.number();\\n\\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\\n if (poolPriceCache.updateBlockNumber == blockNumber) {\\n if (poolPriceCache.isDeviationBreached) {\\n return (poolPriceCache.realPriceX128, poolPriceCache.realPriceX128);\\n } else {\\n return (poolPriceCache.realPriceX128, poolPriceCache.virtualPriceX128);\\n }\\n } else {\\n return protocol.getTwapPricesWithDeviationCheck(poolId);\\n }\\n }\\n\\n function getCachedRealTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\\n internal\\n view\\n returns (uint256 priceX128)\\n {\\n uint32 blockNumber = Block.number();\\n\\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\\n if (poolPriceCache.updateBlockNumber == blockNumber) {\\n return poolPriceCache.realPriceX128;\\n } else {\\n return protocol.getRealTwapPriceX128(poolId);\\n }\\n }\\n\\n /// @notice gets the margin ratio for a poolId\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @param isInitialMargin whether to use initial margin or maintainance margin\\n /// @return margin rato in bps\\n function getMarginRatioBps(\\n Protocol.Info storage protocol,\\n uint32 poolId,\\n bool isInitialMargin\\n ) internal view returns (uint16) {\\n if (isInitialMargin) {\\n return protocol.pools[poolId].settings.initialMarginRatioBps;\\n } else {\\n return protocol.pools[poolId].settings.maintainanceMarginRatioBps;\\n }\\n }\\n\\n /// @notice checks if the pool is cross margined\\n /// @param protocol ref to the protocol state\\n /// @param poolId the poolId of the pool\\n /// @return bool whether the pool is cross margined\\n function isPoolCrossMargined(Protocol.Info storage protocol, uint32 poolId) internal view returns (bool) {\\n return protocol.pools[poolId].settings.isCrossMargined;\\n }\\n\\n /// @notice Gives notional value of the given vToken and vQuote amounts\\n /// @param protocol platform constants\\n /// @param poolId id of the rage trade pool\\n /// @param vTokenAmount amount of tokens\\n /// @param vQuoteAmount amount of base\\n /// @return notionalValue for the given token and vQuote amounts\\n function getNotionalValue(\\n Protocol.Info storage protocol,\\n uint32 poolId,\\n int256 vTokenAmount,\\n int256 vQuoteAmount\\n ) internal view returns (uint256 notionalValue) {\\n return\\n vTokenAmount.absUint().mulDiv(protocol.getCachedVirtualTwapPriceX128(poolId), FixedPoint128.Q128) +\\n vQuoteAmount.absUint();\\n }\\n\\n /// @notice Gives notional value of the given token amount\\n /// @param protocol platform constants\\n /// @param poolId id of the rage trade pool\\n /// @param vTokenAmount amount of tokens\\n /// @return notionalValue for the given token and vQuote amounts\\n function getNotionalValue(\\n Protocol.Info storage protocol,\\n uint32 poolId,\\n int256 vTokenAmount\\n ) internal view returns (uint256 notionalValue) {\\n return protocol.getNotionalValue(poolId, vTokenAmount, 0);\\n }\\n}\\n\",\"keccak256\":\"0x274ddcd8f199b7505377bdeda516d4de0db10dd03222bcdf7eb8fb94ca4092a0\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\n/// @title Safe cast functions\\nlibrary SafeCast {\\n error SafeCast_Int128Overflow(uint128 value);\\n\\n function toInt128(uint128 y) internal pure returns (int128 z) {\\n unchecked {\\n if (y >= 2**127) revert SafeCast_Int128Overflow(y);\\n z = int128(y);\\n }\\n }\\n\\n error SafeCast_Int256Overflow(uint256 value);\\n\\n function toInt256(uint256 y) internal pure returns (int256 z) {\\n unchecked {\\n if (y >= 2**255) revert SafeCast_Int256Overflow(y);\\n z = int256(y);\\n }\\n }\\n\\n error SafeCast_UInt224Overflow(uint256 value);\\n\\n function toUint224(uint256 y) internal pure returns (uint224 z) {\\n if (y > 2**224) revert SafeCast_UInt224Overflow(y);\\n z = uint224(y);\\n }\\n}\\n\",\"keccak256\":\"0xdc96976b23016f06a21a9db7e01c509dff6c9f6ebbdca3dba0043cdfae3405eb\",\"license\":\"MIT\"},\"contracts/libraries/SignedFullMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.0;\\n\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\n\\nimport { SignedMath } from './SignedMath.sol';\\n\\n/// @title Signed full math functions\\nlibrary SignedFullMath {\\n using SafeCast for uint256;\\n using SignedMath for int256;\\n\\n /// @notice uses full math on signed int and two unsigned ints\\n /// @param a: signed int\\n /// @param b: unsigned int to be multiplied by\\n /// @param denominator: unsigned int to be divided by\\n /// @return result of a * b / denominator\\n function mulDiv(\\n int256 a,\\n uint256 b,\\n uint256 denominator\\n ) internal pure returns (int256 result) {\\n result = FullMath.mulDiv(a < 0 ? uint256(-1 * a) : uint256(a), b, denominator).toInt256();\\n if (a < 0) {\\n result = -result;\\n }\\n }\\n\\n /// @notice uses full math on three signed ints\\n /// @param a: signed int\\n /// @param b: signed int to be multiplied by\\n /// @param denominator: signed int to be divided by\\n /// @return result of a * b / denominator\\n function mulDiv(\\n int256 a,\\n int256 b,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n bool resultPositive = true;\\n uint256 _a;\\n uint256 _b;\\n uint256 _denominator;\\n\\n (_a, resultPositive) = a.extractSign(resultPositive);\\n (_b, resultPositive) = b.extractSign(resultPositive);\\n (_denominator, resultPositive) = denominator.extractSign(resultPositive);\\n\\n result = FullMath.mulDiv(_a, _b, _denominator).toInt256();\\n if (!resultPositive) {\\n result = -result;\\n }\\n }\\n\\n /// @notice rounds down towards negative infinity\\n /// @dev in Solidity -3/2 is -1. But this method result is -2\\n /// @param a: signed int\\n /// @param b: unsigned int to be multiplied by\\n /// @param denominator: unsigned int to be divided by\\n /// @return result of a * b / denominator rounded towards negative infinity\\n function mulDivRoundingDown(\\n int256 a,\\n uint256 b,\\n uint256 denominator\\n ) internal pure returns (int256 result) {\\n result = mulDiv(a, b, denominator);\\n if (result < 0 && _hasRemainder(a.absUint(), b, denominator)) {\\n result += -1;\\n }\\n }\\n\\n /// @notice rounds down towards negative infinity\\n /// @dev in Solidity -3/2 is -1. But this method result is -2\\n /// @param a: signed int\\n /// @param b: signed int to be multiplied by\\n /// @param denominator: signed int to be divided by\\n /// @return result of a * b / denominator rounded towards negative infinity\\n function mulDivRoundingDown(\\n int256 a,\\n int256 b,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n result = mulDiv(a, b, denominator);\\n if (result < 0 && _hasRemainder(a.absUint(), b.absUint(), denominator.absUint())) {\\n result += -1;\\n }\\n }\\n\\n /// @notice checks if full multiplication of a & b would have a remainder if divided by denominator\\n /// @param a: multiplicand\\n /// @param b: multiplier\\n /// @param denominator: divisor\\n /// @return hasRemainder true if there is a remainder, false otherwise\\n function _hasRemainder(\\n uint256 a,\\n uint256 b,\\n uint256 denominator\\n ) private pure returns (bool hasRemainder) {\\n assembly {\\n let remainder := mulmod(a, b, denominator)\\n if gt(remainder, 0) {\\n hasRemainder := 1\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6b5879e3d8f8c0ef8583034f007af7f5d566bc512ea15ab0a26eeeed1092ede3\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nint256 constant ONE = 1;\\n\\n/// @title Signed math functions\\nlibrary SignedMath {\\n /// @notice gives the absolute value of a signed int\\n /// @param value signed int\\n /// @return absolute value of signed int\\n function abs(int256 value) internal pure returns (int256) {\\n return value > 0 ? value : -value;\\n }\\n\\n /// @notice gives the absolute value of a signed int\\n /// @param value signed int\\n /// @return absolute value of signed int as unsigned int\\n function absUint(int256 value) internal pure returns (uint256) {\\n return uint256(abs(value));\\n }\\n\\n /// @notice gives the sign of a signed int\\n /// @param value signed int\\n /// @return -1 if negative, 1 if non-negative\\n function sign(int256 value) internal pure returns (int256) {\\n return value >= 0 ? ONE : -ONE;\\n }\\n\\n /// @notice converts a signed integer into an unsigned integer and inverts positive bool if negative\\n /// @param a signed int\\n /// @param positive initial value of positive bool\\n /// @return _a absolute value of int provided\\n /// @return bool xor of the positive boolean and sign of the provided int\\n function extractSign(int256 a, bool positive) internal pure returns (uint256 _a, bool) {\\n if (a < 0) {\\n positive = !positive;\\n _a = uint256(-a);\\n } else {\\n _a = uint256(a);\\n }\\n return (_a, positive);\\n }\\n\\n /// @notice extracts the sign of a signed int\\n /// @param a signed int\\n /// @return _a unsigned int\\n /// @return bool sign of the provided int\\n function extractSign(int256 a) internal pure returns (uint256 _a, bool) {\\n return extractSign(a, true);\\n }\\n\\n /// @notice returns the max of two int256 numbers\\n /// @param a first number\\n /// @param b second number\\n /// @return c = max of a and b\\n function max(int256 a, int256 b) internal pure returns (int256 c) {\\n if (a > b) c = a;\\n else c = b;\\n }\\n}\\n\",\"keccak256\":\"0xe8218625e89406a3695c78794ec72eea5c3a4db9ef677ce6c36037d5f0431258\",\"license\":\"MIT\"},\"contracts/libraries/Uint32L8Array.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\n/// @title Uint32 length 8 array functions\\n/// @dev Fits in one storage slot\\nlibrary Uint32L8ArrayLib {\\n using Uint32L8ArrayLib for uint32[8];\\n\\n uint8 constant LENGTH = 8;\\n\\n error U32L8_IllegalElement(uint32 element);\\n error U32L8_NoSpaceLeftToInsert(uint32 element);\\n\\n /// @notice Inserts an element in the array\\n /// @dev Replaces a zero value in the array with element\\n /// @param array Array to modify\\n /// @param element Element to insert\\n function include(uint32[8] storage array, uint32 element) internal {\\n if (element == 0) {\\n revert U32L8_IllegalElement(0);\\n }\\n\\n uint256 emptyIndex = LENGTH; // LENGTH is an invalid index\\n for (uint256 i; i < LENGTH; i++) {\\n if (array[i] == element) {\\n // if element already exists in the array, do nothing\\n return;\\n }\\n // if we found an empty slot, remember it\\n if (array[i] == uint32(0)) {\\n emptyIndex = i;\\n break;\\n }\\n }\\n\\n // if empty index is still LENGTH, there is no space left to insert\\n if (emptyIndex == LENGTH) {\\n revert U32L8_NoSpaceLeftToInsert(element);\\n }\\n\\n array[emptyIndex] = element;\\n }\\n\\n /// @notice Excludes the element from the array\\n /// @dev If element exists, it swaps with last element and makes last element zero\\n /// @param array Array to modify\\n /// @param element Element to remove\\n function exclude(uint32[8] storage array, uint32 element) internal {\\n if (element == 0) {\\n revert U32L8_IllegalElement(0);\\n }\\n\\n uint256 elementIndex = LENGTH; // LENGTH is an invalid index\\n uint256 i;\\n\\n for (; i < LENGTH; i++) {\\n if (array[i] == element) {\\n // element index in the array\\n elementIndex = i;\\n }\\n if (array[i] == 0) {\\n // last non-zero element\\n i = i > 0 ? i - 1 : 0;\\n break;\\n }\\n }\\n\\n // if array is full, i == LENGTH\\n // hence swapping with element at last index\\n i = i == LENGTH ? LENGTH - 1 : i;\\n\\n if (elementIndex != LENGTH) {\\n if (i == elementIndex) {\\n // if element is last element, simply make it zero\\n array[elementIndex] = 0;\\n } else {\\n // move last to element's place and empty lastIndex slot\\n (array[elementIndex], array[i]) = (array[i], 0);\\n }\\n }\\n }\\n\\n /// @notice Returns the index of the element in the array\\n /// @param array Array to perform search on\\n /// @param element Element to search\\n /// @return index if exists or LENGTH otherwise\\n function indexOf(uint32[8] storage array, uint32 element) internal view returns (uint8) {\\n for (uint8 i; i < LENGTH; i++) {\\n if (array[i] == element) {\\n return i;\\n }\\n }\\n return LENGTH; // LENGTH is an invalid index\\n }\\n\\n /// @notice Checks whether the element exists in the array\\n /// @param array Array to perform search on\\n /// @param element Element to search\\n /// @return True if element is found, false otherwise\\n function exists(uint32[8] storage array, uint32 element) internal view returns (bool) {\\n return array.indexOf(element) != LENGTH; // LENGTH is an invalid index\\n }\\n\\n /// @notice Returns length of array (number of non-zero elements)\\n /// @param array Array to perform search on\\n /// @return Length of array\\n function numberOfNonZeroElements(uint32[8] storage array) internal view returns (uint256) {\\n for (uint8 i; i < LENGTH; i++) {\\n if (array[i] == 0) {\\n return i;\\n }\\n }\\n return LENGTH;\\n }\\n\\n /// @notice Checks whether the array is empty or not\\n /// @param array Array to perform search on\\n /// @return True if the set does not have any token position active\\n function isEmpty(uint32[8] storage array) internal view returns (bool) {\\n return array[0] == 0;\\n }\\n}\\n\",\"keccak256\":\"0x19d249c0ea7212d517f47603e41606eb0d17f60b64b8d6750f36f578e9d4ea88\",\"license\":\"MIT\"},\"contracts/libraries/Uint48.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\n/// @title Uint48 concating functions\\nlibrary Uint48Lib {\\n /// @notice Packs two int24 values into uint48\\n /// @dev Used for concating two ticks into 48 bits value\\n /// @param val1 First 24 bits value\\n /// @param val2 Second 24 bits value\\n /// @return concatenated value\\n function concat(int24 val1, int24 val2) internal pure returns (uint48 concatenated) {\\n assembly {\\n concatenated := add(shl(24, val1), and(val2, 0x000000ffffff))\\n }\\n }\\n\\n /// @notice Unpacks uint48 into two int24 values\\n /// @dev Used for unpacking 48 bits value into two 24 bits values\\n /// @param concatenated 48 bits value\\n /// @return val1 First 24 bits value\\n /// @return val2 Second 24 bits value\\n function unconcat(uint48 concatenated) internal pure returns (int24 val1, int24 val2) {\\n assembly {\\n val2 := concatenated\\n val1 := shr(24, concatenated)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x68c948293e2c5ee54c07b65af3a3713c5ddc9d2ae68dbc4ada6757773046f475\",\"license\":\"MIT\"},\"contracts/libraries/Uint48L5Array.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\n/// @title Uint48 length 5 array functions\\n/// @dev Fits in one storage slot\\nlibrary Uint48L5ArrayLib {\\n using Uint48L5ArrayLib for uint48[5];\\n\\n uint8 constant LENGTH = 5;\\n\\n error U48L5_IllegalElement(uint48 element);\\n error U48L5_NoSpaceLeftToInsert(uint48 element);\\n\\n /// @notice Inserts an element in the array\\n /// @dev Replaces a zero value in the array with element\\n /// @param array Array to modify\\n /// @param element Element to insert\\n function include(uint48[5] storage array, uint48 element) internal {\\n if (element == 0) {\\n revert U48L5_IllegalElement(0);\\n }\\n\\n uint256 emptyIndex = LENGTH; // LENGTH is an invalid index\\n for (uint256 i; i < LENGTH; i++) {\\n if (array[i] == element) {\\n // if element already exists in the array, do nothing\\n return;\\n }\\n // if we found an empty slot, remember it\\n if (array[i] == uint48(0)) {\\n emptyIndex = i;\\n break;\\n }\\n }\\n\\n // if empty index is still LENGTH, there is no space left to insert\\n if (emptyIndex == LENGTH) {\\n revert U48L5_NoSpaceLeftToInsert(element);\\n }\\n\\n array[emptyIndex] = element;\\n }\\n\\n /// @notice Excludes the element from the array\\n /// @dev If element exists, it swaps with last element and makes last element zero\\n /// @param array Array to modify\\n /// @param element Element to remove\\n function exclude(uint48[5] storage array, uint48 element) internal {\\n if (element == 0) {\\n revert U48L5_IllegalElement(0);\\n }\\n\\n uint256 elementIndex = LENGTH; // LENGTH is an invalid index\\n uint256 i;\\n\\n for (; i < LENGTH; i++) {\\n if (array[i] == element) {\\n // element index in the array\\n elementIndex = i;\\n }\\n if (array[i] == 0) {\\n // last non-zero element\\n i = i > 0 ? i - 1 : 0;\\n break;\\n }\\n }\\n\\n // if array is full, i == LENGTH\\n // hence swapping with element at last index\\n i = i == LENGTH ? LENGTH - 1 : i;\\n\\n if (elementIndex != LENGTH) {\\n if (i == elementIndex) {\\n // if element is last element, simply make it zero\\n array[elementIndex] = 0;\\n } else {\\n // move last to element's place and empty lastIndex slot\\n (array[elementIndex], array[i]) = (array[i], 0);\\n }\\n }\\n }\\n\\n /// @notice Returns the index of the element in the array\\n /// @param array Array to perform search on\\n /// @param element Element to search\\n /// @return index if exists or LENGTH otherwise\\n function indexOf(uint48[5] storage array, uint48 element) internal view returns (uint8) {\\n for (uint8 i; i < LENGTH; i++) {\\n if (array[i] == element) {\\n return i;\\n }\\n }\\n return LENGTH; // LENGTH is an invalid index\\n }\\n\\n /// @notice Checks whether the element exists in the array\\n /// @param array Array to perform search on\\n /// @param element Element to search\\n /// @return True if element is found, false otherwise\\n function exists(uint48[5] storage array, uint48 element) internal view returns (bool) {\\n return array.indexOf(element) != LENGTH; // LENGTH is an invalid index\\n }\\n\\n /// @notice Returns length of array (number of non-zero elements)\\n /// @param array Array to perform search on\\n /// @return Length of array\\n function numberOfNonZeroElements(uint48[5] storage array) internal view returns (uint256) {\\n for (uint8 i; i < LENGTH; i++) {\\n if (array[i] == 0) {\\n return i;\\n }\\n }\\n return LENGTH;\\n }\\n\\n /// @notice Checks whether the array is empty or not\\n /// @param array Array to perform search on\\n /// @return True if the set does not have any token position active\\n function isEmpty(uint48[5] storage array) internal view returns (bool) {\\n return array[0] == 0;\\n }\\n}\\n\",\"keccak256\":\"0x31b9d020b860bda93859895fac5cb619c791a8e370d59ebb9fa4f1d81edbc070\",\"license\":\"MIT\"},\"contracts/libraries/UniswapV3PoolHelper.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity ^0.8.4;\\n\\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\\n\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\n/// @title UniswapV3Pool helper functions\\nlibrary UniswapV3PoolHelper {\\n using UniswapV3PoolHelper for IUniswapV3Pool;\\n\\n error UV3PH_OracleConsultFailed();\\n\\n /// @notice Get the pool's current tick\\n /// @param v3Pool The uniswap v3 pool contract\\n /// @return tick the current tick\\n function tickCurrent(IUniswapV3Pool v3Pool) internal view returns (int24 tick) {\\n (, tick, , , , , ) = v3Pool.slot0();\\n }\\n\\n /// @notice Get the pool's current sqrt price\\n /// @param v3Pool The uniswap v3 pool contract\\n /// @return sqrtPriceX96 the current sqrt price\\n function sqrtPriceCurrent(IUniswapV3Pool v3Pool) internal view returns (uint160 sqrtPriceX96) {\\n (sqrtPriceX96, , , , , , ) = v3Pool.slot0();\\n }\\n\\n /// @notice Get twap price for uniswap v3 pool\\n /// @param v3Pool The uniswap v3 pool contract\\n /// @param twapDuration The twap period\\n /// @return sqrtPriceX96 the twap price\\n function twapSqrtPrice(IUniswapV3Pool v3Pool, uint32 twapDuration) internal view returns (uint160 sqrtPriceX96) {\\n int24 _twapTick = v3Pool.twapTick(twapDuration);\\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_twapTick);\\n }\\n\\n /// @notice Get twap tick for uniswap v3 pool\\n /// @param v3Pool The uniswap v3 pool contract\\n /// @param twapDuration The twap period\\n /// @return _twapTick the twap tick\\n function twapTick(IUniswapV3Pool v3Pool, uint32 twapDuration) internal view returns (int24 _twapTick) {\\n if (twapDuration == 0) {\\n return v3Pool.tickCurrent();\\n }\\n\\n uint32[] memory secondAgos = new uint32[](2);\\n secondAgos[0] = twapDuration;\\n secondAgos[1] = 0;\\n\\n // this call will fail if period is bigger than MaxObservationPeriod\\n try v3Pool.observe(secondAgos) returns (int56[] memory tickCumulatives, uint160[] memory) {\\n int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n int24 timeWeightedAverageTick = int24(tickCumulativesDelta / int56(uint56(twapDuration)));\\n\\n // Always round to negative infinity\\n if (tickCumulativesDelta < 0 && (tickCumulativesDelta % int56(uint56(twapDuration)) != 0)) {\\n timeWeightedAverageTick--;\\n }\\n return timeWeightedAverageTick;\\n } catch {\\n // if for some reason v3Pool.observe fails, fallback to the current tick\\n (, _twapTick, , , , , ) = v3Pool.slot0();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c14ffade5bbb417584a69e08cf4005abde9af5c24e70042db815a6bad2e7b29\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/VTokenPosition.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport { FundingPayment } from './FundingPayment.sol';\\nimport { LiquidityPosition } from './LiquidityPosition.sol';\\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\\n\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\n\\n/// @title VToken position functions\\nlibrary VTokenPosition {\\n using FullMath for uint256;\\n using SignedFullMath for int256;\\n using UniswapV3PoolHelper for IUniswapV3Pool;\\n\\n using LiquidityPosition for LiquidityPosition.Info;\\n using LiquidityPositionSet for LiquidityPosition.Set;\\n using Protocol for Protocol.Info;\\n\\n enum RISK_SIDE {\\n LONG,\\n SHORT\\n }\\n\\n struct Set {\\n // Fixed length array of poolId = vTokenAddress.truncate()\\n // Open positions in 8 different pairs at same time.\\n // Collision between poolId is not possible.\\n uint32[8] active; // array of poolIds\\n mapping(uint32 => VTokenPosition.Info) positions; // poolId => Position\\n int256 vQuoteBalance;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n struct Info {\\n int256 balance; // vTokenLong - vTokenShort\\n int256 netTraderPosition;\\n int256 sumALastX128;\\n // this is moved from accounts to here because of the in margin available check\\n // the loop needs to be done over liquidity positions of same token only\\n LiquidityPosition.Set liquidityPositions;\\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\\n }\\n\\n /// @notice Gives the market value of the supplied token position\\n /// @param position token position\\n /// @param priceX128 price in Q128\\n /// @param wrapper pool wrapper corresponding to position\\n /// @return value market value with 6 decimals\\n function marketValue(\\n VTokenPosition.Info storage position,\\n uint256 priceX128,\\n IVPoolWrapper wrapper\\n ) internal view returns (int256 value) {\\n value = position.balance.mulDiv(priceX128, FixedPoint128.Q128);\\n value += unrealizedFundingPayment(position, wrapper);\\n }\\n\\n /// @notice returns the market value of the supplied token position\\n /// @param position token position\\n /// @param priceX128 price in Q128\\n /// @param poolId id of the rage trade pool\\n /// @param protocol ref to the protocol state\\n function marketValue(\\n VTokenPosition.Info storage position,\\n uint32 poolId,\\n uint256 priceX128,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 value) {\\n return marketValue(position, priceX128, protocol.vPoolWrapper(poolId));\\n }\\n\\n /// @notice returns the market value of the supplied token position\\n /// @param position token position\\n /// @param poolId id of the rage trade pool\\n /// @param protocol ref to the protocol state\\n function marketValue(\\n VTokenPosition.Info storage position,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256) {\\n uint256 priceX128 = protocol.getCachedVirtualTwapPriceX128(poolId);\\n return marketValue(position, poolId, priceX128, protocol);\\n }\\n\\n function riskSide(VTokenPosition.Info storage position) internal view returns (RISK_SIDE) {\\n return position.balance > 0 ? RISK_SIDE.LONG : RISK_SIDE.SHORT;\\n }\\n\\n /// @notice returns the vQuoteIncrease due to unrealized funding payment for the trader position (+ve means receiving and -ve means paying)\\n /// @param position token position\\n /// @param wrapper pool wrapper corresponding to position\\n /// @return unrealizedFpBill funding to be realized (+ve means receive and -ve means pay)\\n function unrealizedFundingPayment(VTokenPosition.Info storage position, IVPoolWrapper wrapper)\\n internal\\n view\\n returns (int256)\\n {\\n int256 extrapolatedSumAX128 = wrapper.getExtrapolatedSumAX128();\\n int256 vQuoteIncrease = -FundingPayment.bill(\\n extrapolatedSumAX128,\\n position.sumALastX128,\\n position.netTraderPosition\\n );\\n return vQuoteIncrease;\\n }\\n\\n /// @notice gets the account's net position for a given poolId\\n /// @param position token position\\n /// @param poolId id of the rage trade pool\\n /// @param protocol ref to the protocol state\\n /// @return net position\\n function getNetPosition(\\n VTokenPosition.Info storage position,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256) {\\n return\\n position.netTraderPosition +\\n position.liquidityPositions.getNetPosition(protocol.vPool(poolId).sqrtPriceCurrent());\\n }\\n}\\n\",\"keccak256\":\"0x9fbaf7aa199362453c1805021018327619e102df5131410a6872bea6965462fa\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/VTokenPositionSet.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity ^0.8.4;\\n\\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\\n\\nimport { AddressHelper } from './AddressHelper.sol';\\nimport { LiquidityPosition } from './LiquidityPosition.sol';\\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\\nimport { Protocol } from './Protocol.sol';\\nimport { PriceMath } from './PriceMath.sol';\\nimport { SignedFullMath } from './SignedFullMath.sol';\\nimport { SignedMath } from './SignedMath.sol';\\nimport { VTokenPosition } from './VTokenPosition.sol';\\nimport { Uint32L8ArrayLib } from './Uint32L8Array.sol';\\n\\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\\nimport { IVToken } from '../interfaces/IVToken.sol';\\n\\n/// @title VToken position set functions\\nlibrary VTokenPositionSet {\\n using AddressHelper for address;\\n using FullMath for uint256;\\n using PriceMath for uint256;\\n using SafeCast for uint256;\\n using SignedFullMath for int256;\\n using SignedMath for int256;\\n using Uint32L8ArrayLib for uint32[8];\\n\\n using LiquidityPositionSet for LiquidityPosition.Set;\\n using Protocol for Protocol.Info;\\n using VTokenPosition for VTokenPosition.Info;\\n using VTokenPositionSet for VTokenPosition.Set;\\n\\n error VPS_IncorrectUpdate();\\n error VPS_DeactivationFailed(uint32 poolId);\\n error VPS_TokenInactive(uint32 poolId);\\n\\n /// @notice denotes token position change\\n /// @param accountId serial number of the account\\n /// @param poolId truncated address of vtoken whose position was taken\\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\\n /// @param vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\\n /// @param sqrtPriceX96Start shows the sqrtPriceX96 at the start of trade execution, can be 0 if not on v3Pool\\n /// @param sqrtPriceX96End shows the sqrtPriceX96 at the end of trade execution, can be 0 if not on v3Pool\\n event TokenPositionChanged(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int256 vTokenAmountOut,\\n int256 vQuoteAmountOut,\\n uint160 sqrtPriceX96Start,\\n uint160 sqrtPriceX96End\\n );\\n\\n /// @notice denotes funding payment for a range / token position\\n /// @param accountId serial number of the account\\n /// @param poolId address of token for which funding was paid\\n /// @param amount amount of funding paid (negative) or received (positive)\\n /// @param sumALastX128 val of sum of the term A in funding payment math, when op took place\\n event TokenPositionFundingPaymentRealized(\\n uint256 indexed accountId,\\n uint32 indexed poolId,\\n int256 amount,\\n int256 sumALastX128\\n );\\n\\n /**\\n * Internal methods\\n */\\n\\n /// @notice activates token with address 'vToken' if not already active\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n function activate(VTokenPosition.Set storage set, uint32 poolId) internal {\\n set.active.include(poolId);\\n }\\n\\n /// @notice deactivates token with address 'vToken'\\n /// @dev ensures that the balance is 0 and there are not range positions active otherwise throws an error\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n function deactivate(VTokenPosition.Set storage set, uint32 poolId) internal {\\n if (set.positions[poolId].balance != 0 || !set.positions[poolId].liquidityPositions.isEmpty()) {\\n revert VPS_DeactivationFailed(poolId);\\n }\\n\\n set.active.exclude(poolId);\\n }\\n\\n /// @notice updates token balance, net trader position and vQuote balance\\n /// @dev realizes funding payment to vQuote balance\\n /// @dev activates the token if not already active\\n /// @dev deactivates the token if the balance = 0 and there are no range positions active\\n /// @dev IMP: ensure that the global states are updated using zeroSwap or directly through some interaction with pool wrapper\\n /// @param set VTokenPositionSet\\n /// @param balanceAdjustments platform constants\\n /// @param poolId id of the rage trade pool\\n /// @param accountId account identifier, used for emitting event\\n /// @param protocol platform constants\\n function update(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal {\\n set.realizeFundingPayment(accountId, poolId, protocol);\\n set.active.include(poolId);\\n\\n VTokenPosition.Info storage _VTokenPosition = set.positions[poolId];\\n _VTokenPosition.balance += balanceAdjustments.vTokenIncrease;\\n _VTokenPosition.netTraderPosition += balanceAdjustments.traderPositionIncrease;\\n\\n set.vQuoteBalance += balanceAdjustments.vQuoteIncrease;\\n\\n if (_VTokenPosition.balance == 0 && _VTokenPosition.liquidityPositions.active[0] == 0) {\\n set.deactivate(poolId);\\n }\\n }\\n\\n /// @notice realizes funding payment to vQuote balance\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n /// @param accountId account identifier, used for emitting event\\n /// @param protocol platform constants\\n function realizeFundingPayment(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal {\\n set.realizeFundingPayment(accountId, poolId, protocol.pools[poolId].vPoolWrapper);\\n }\\n\\n /// @notice realizes funding payment to vQuote balance\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n /// @param accountId account identifier, used for emitting event\\n /// @param wrapper VPoolWrapper to override the set wrapper\\n function realizeFundingPayment(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IVPoolWrapper wrapper\\n ) internal {\\n VTokenPosition.Info storage position = set.positions[poolId];\\n int256 extrapolatedSumAX128 = wrapper.getSumAX128();\\n\\n int256 fundingPayment = position.unrealizedFundingPayment(wrapper);\\n set.vQuoteBalance += fundingPayment;\\n\\n position.sumALastX128 = extrapolatedSumAX128;\\n\\n emit TokenPositionFundingPaymentRealized(accountId, poolId, fundingPayment, extrapolatedSumAX128);\\n }\\n\\n /// @notice swaps tokens (Long and Short) with input in token amount / vQuote amount\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param swapParams parameters for swap\\n /// @param protocol platform constants\\n /// @return vTokenAmountOut - token amount coming out of pool\\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\\n function swapToken(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.SwapParams memory swapParams,\\n Protocol.Info storage protocol\\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n return set.swapToken(accountId, poolId, swapParams, protocol.vPoolWrapper(poolId), protocol);\\n }\\n\\n /// @notice swaps tokens (Long and Short) with input in token amount\\n /// @dev activates inactive vToe\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param vTokenAmount amount of the token\\n /// @param protocol platform constants\\n /// @return vTokenAmountOut - token amount coming out of pool\\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\\n function swapTokenAmount(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n int256 vTokenAmount,\\n Protocol.Info storage protocol\\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n return\\n set.swapToken(\\n accountId,\\n poolId,\\n /// @dev 0 means no price limit and false means amount mentioned is token amount\\n IClearingHouseStructures.SwapParams({\\n amount: vTokenAmount,\\n sqrtPriceLimit: 0,\\n isNotional: false,\\n isPartialAllowed: false,\\n settleProfit: false\\n }),\\n protocol.vPoolWrapper(poolId),\\n protocol\\n );\\n }\\n\\n /// @notice swaps tokens (Long and Short) with input in token amount / vQuote amount\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param swapParams parameters for swap\\n /// @param wrapper VPoolWrapper to override the set wrapper\\n /// @param protocol platform constants\\n /// @return vTokenAmountOut - token amount coming out of pool\\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\\n function swapToken(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.SwapParams memory swapParams,\\n IVPoolWrapper wrapper,\\n Protocol.Info storage protocol\\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n IVPoolWrapper.SwapResult memory swapResult = wrapper.swap(\\n swapParams.amount < 0,\\n swapParams.isNotional ? swapParams.amount : -swapParams.amount,\\n swapParams.sqrtPriceLimit\\n );\\n\\n // change direction basis uniswap to balance increase\\n vTokenAmountOut = -swapResult.vTokenIn;\\n vQuoteAmountOut = -swapResult.vQuoteIn;\\n\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments = IClearingHouseStructures\\n .BalanceAdjustments(vQuoteAmountOut, vTokenAmountOut, vTokenAmountOut);\\n\\n set.update(accountId, balanceAdjustments, poolId, protocol);\\n\\n emit TokenPositionChanged(\\n accountId,\\n poolId,\\n vTokenAmountOut,\\n vQuoteAmountOut,\\n swapResult.sqrtPriceX96Start,\\n swapResult.sqrtPriceX96End\\n );\\n }\\n\\n /// @notice function to liquidate all liquidity positions\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param protocol platform constants\\n /// @return notionalAmountClosed - value of net token position coming out (in notional) of all the ranges closed\\n function liquidateLiquidityPositions(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n Protocol.Info storage protocol\\n ) internal returns (uint256 notionalAmountClosed) {\\n for (uint8 i = 0; i < set.active.length; i++) {\\n uint32 truncated = set.active[i];\\n if (truncated == 0) break;\\n\\n notionalAmountClosed += set.liquidateLiquidityPositions(accountId, set.active[i], protocol);\\n }\\n }\\n\\n /// @notice function to liquidate liquidity positions for a particular token\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param protocol platform constants\\n /// @return notionalAmountClosed - value of net token position coming out (in notional) of all the ranges closed\\n function liquidateLiquidityPositions(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal returns (uint256 notionalAmountClosed) {\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\\n\\n set.getTokenPosition(poolId, false).liquidityPositions.closeAllLiquidityPositions(\\n accountId,\\n poolId,\\n balanceAdjustments,\\n protocol\\n );\\n\\n set.update(accountId, balanceAdjustments, poolId, protocol);\\n\\n // returns notional value of token position closed\\n return protocol.getNotionalValue(poolId, balanceAdjustments.traderPositionIncrease);\\n }\\n\\n /// @notice function for liquidity add/remove\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param liquidityChangeParams includes tickLower, tickUpper, liquidityDelta, limitOrderType\\n /// @return vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\\n /// @return vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\\n function liquidityChange(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\\n Protocol.Info storage protocol\\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, true);\\n\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\\n\\n vTokenPosition.liquidityPositions.liquidityChange(\\n accountId,\\n poolId,\\n liquidityChangeParams,\\n balanceAdjustments,\\n protocol\\n );\\n\\n set.update(accountId, balanceAdjustments, poolId, protocol);\\n\\n if (liquidityChangeParams.closeTokenPosition && balanceAdjustments.traderPositionIncrease != 0) {\\n set.swapTokenAmount(accountId, poolId, -balanceAdjustments.traderPositionIncrease, protocol);\\n }\\n\\n return (balanceAdjustments.vTokenIncrease, balanceAdjustments.vQuoteIncrease);\\n }\\n\\n /// @notice function to remove an eligible limit order\\n /// @dev checks whether the current price is on the correct side of the range based on the type of limit order (None, Low, High)\\n /// @param set VTokenPositionSet\\n /// @param accountId account identifier, used for emitting event\\n /// @param poolId id of the rage trade pool\\n /// @param tickLower lower tick index for the range\\n /// @param tickUpper upper tick index for the range\\n /// @param protocol platform constants\\n function removeLimitOrder(\\n VTokenPosition.Set storage set,\\n uint256 accountId,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper,\\n Protocol.Info storage protocol\\n ) internal {\\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, false);\\n\\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\\n int24 currentTick = protocol.getVirtualCurrentTick(poolId);\\n\\n vTokenPosition.liquidityPositions.removeLimitOrder(\\n accountId,\\n poolId,\\n currentTick,\\n tickLower,\\n tickUpper,\\n balanceAdjustments,\\n protocol\\n );\\n\\n set.update(accountId, balanceAdjustments, poolId, protocol);\\n }\\n\\n function updateOpenPoolPrices(VTokenPosition.Set storage set, Protocol.Info storage protocol) internal {\\n for (uint8 i = 0; i < set.active.length; i++) {\\n uint32 poolId = set.active[i];\\n if (poolId == 0) break;\\n protocol.updatePoolPriceCache(poolId);\\n }\\n }\\n\\n /**\\n * Internal view methods\\n */\\n\\n /// @notice returns account market value of active positions\\n /// @param set VTokenPositionSet\\n /// @param protocol platform constants\\n /// @return accountMarketValue - value of all active positions\\n function getAccountMarketValue(VTokenPosition.Set storage set, Protocol.Info storage protocol)\\n internal\\n view\\n returns (int256 accountMarketValue)\\n {\\n for (uint8 i = 0; i < set.active.length; i++) {\\n uint32 poolId = set.active[i];\\n if (poolId == 0) break;\\n // IVToken vToken = protocol[poolId].vToken;\\n VTokenPosition.Info storage position = set.positions[poolId];\\n\\n (, uint256 virtualPriceX128) = protocol.getCachedTwapPricesWithDeviationCheck(poolId);\\n uint160 virtualSqrtPriceX96 = virtualPriceX128.toSqrtPriceX96();\\n //Value of token position for current vToken\\n accountMarketValue += position.marketValue(poolId, virtualPriceX128, protocol);\\n\\n //Value of all active range position for the current vToken\\n accountMarketValue += position.liquidityPositions.marketValue(virtualSqrtPriceX96, poolId, protocol);\\n }\\n\\n // Value of the vQuote token balance\\n accountMarketValue += set.vQuoteBalance;\\n }\\n\\n /// @notice gets information about the token and liquidity positions for all the pools\\n /// @param set VTokenPositionSet\\n /// @return vQuoteBalance vQuote balance for the token position\\n /// @return vTokenPositions array of vToken position\\n function getInfo(VTokenPosition.Set storage set)\\n internal\\n view\\n returns (int256 vQuoteBalance, IClearingHouseStructures.VTokenPositionView[] memory vTokenPositions)\\n {\\n vQuoteBalance = set.vQuoteBalance;\\n\\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\\n vTokenPositions = new IClearingHouseStructures.VTokenPositionView[](numberOfTokenPositions);\\n\\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\\n vTokenPositions[i].poolId = set.active[i];\\n vTokenPositions[i].balance = set.positions[set.active[i]].balance;\\n vTokenPositions[i].netTraderPosition = set.positions[set.active[i]].netTraderPosition;\\n vTokenPositions[i].sumALastX128 = set.positions[set.active[i]].sumALastX128;\\n vTokenPositions[i].liquidityPositions = set.positions[set.active[i]].liquidityPositions.getInfo();\\n }\\n }\\n\\n /// @notice returns the long and short side risk for range positions of a particular token\\n /// @param set VTokenPositionSet\\n /// @param isInitialMargin specifies to use initial margin factor (true) or maintainance margin factor (false)\\n /// @param poolId id of the rage trade pool\\n /// @param protocol platform constants\\n /// @return longSideRisk - risk if the token price goes down\\n /// @return shortSideRisk - risk if the token price goes up\\n function getLongShortSideRisk(\\n VTokenPosition.Set storage set,\\n bool isInitialMargin,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 longSideRisk, int256 shortSideRisk) {\\n VTokenPosition.Info storage position = set.positions[poolId];\\n\\n (, uint256 virtualPriceX128) = protocol.getCachedTwapPricesWithDeviationCheck(poolId);\\n uint160 virtualSqrtPriceX96 = virtualPriceX128.toSqrtPriceX96();\\n\\n uint16 marginRatio = protocol.getMarginRatioBps(poolId, isInitialMargin);\\n\\n int256 tokenPosition = position.balance;\\n int256 longSideRiskRanges = position.liquidityPositions.longSideRisk(virtualSqrtPriceX96).toInt256();\\n\\n longSideRisk = SignedMath\\n .max(position.netTraderPosition.mulDiv(virtualPriceX128, FixedPoint128.Q128) + longSideRiskRanges, 0)\\n .mulDiv(marginRatio, 1e4);\\n\\n shortSideRisk = SignedMath.max(-tokenPosition, 0).mulDiv(virtualPriceX128, FixedPoint128.Q128).mulDiv(\\n marginRatio,\\n 1e4\\n );\\n return (longSideRisk, shortSideRisk);\\n }\\n\\n /// @notice gets the net position for the given poolId\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n /// @param protocol platform constants\\n /// @return netPosition net position of the account for the pool\\n function getNetPosition(\\n VTokenPosition.Set storage set,\\n uint32 poolId,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 netPosition) {\\n if (!set.active.exists(poolId)) return 0;\\n VTokenPosition.Info storage tokenPosition = set.positions[poolId];\\n return tokenPosition.getNetPosition(poolId, protocol);\\n }\\n\\n /// @notice returns the long and short side risk for range positions of a particular token\\n /// @param set VTokenPositionSet\\n /// @param isInitialMargin specifies to use initial margin factor (true) or maintainance margin factor (false)\\n /// @param protocol platform constants\\n /// @return requiredMargin - required margin value based on the current active positions\\n function getRequiredMargin(\\n VTokenPosition.Set storage set,\\n bool isInitialMargin,\\n Protocol.Info storage protocol\\n ) internal view returns (int256 requiredMargin) {\\n int256 longSideRiskTotal;\\n int256 shortSideRiskTotal;\\n int256 longSideRisk;\\n int256 shortSideRisk;\\n for (uint8 i = 0; i < set.active.length; i++) {\\n if (set.active[i] == 0) break;\\n uint32 poolId = set.active[i];\\n (longSideRisk, shortSideRisk) = set.getLongShortSideRisk(isInitialMargin, poolId, protocol);\\n\\n if (protocol.isPoolCrossMargined(poolId)) {\\n longSideRiskTotal += longSideRisk;\\n shortSideRiskTotal += shortSideRisk;\\n } else {\\n requiredMargin += SignedMath.max(longSideRisk, shortSideRisk);\\n }\\n }\\n\\n requiredMargin += SignedMath.max(longSideRiskTotal, shortSideRiskTotal);\\n }\\n\\n /// @notice get or create token position\\n /// @dev activates inactive vToken if isCreateNew is true else reverts\\n /// @param set VTokenPositionSet\\n /// @param poolId id of the rage trade pool\\n /// @param createNew if 'vToken' is inactive then activates (true) else reverts with TokenInactive(false)\\n /// @return position - VTokenPosition corresponding to 'vToken'\\n function getTokenPosition(\\n VTokenPosition.Set storage set,\\n uint32 poolId,\\n bool createNew\\n ) internal returns (VTokenPosition.Info storage position) {\\n if (createNew) {\\n set.activate(poolId);\\n } else if (!set.active.exists(poolId)) {\\n revert VPS_TokenInactive(poolId);\\n }\\n\\n position = set.positions[poolId];\\n }\\n\\n /// @notice returns true if the set does not have any token position active\\n /// @param set VTokenPositionSet\\n /// @return True if there are no active positions\\n function isEmpty(VTokenPosition.Set storage set) internal view returns (bool) {\\n return set.active.isEmpty();\\n }\\n\\n /// @notice returns true if range position is active for 'vToken'\\n /// @param set VTokenPositionSet\\n /// @param poolId poolId of the vToken\\n /// @return isRangeActive - True if the range position is active\\n function isTokenRangeActive(VTokenPosition.Set storage set, uint32 poolId) internal returns (bool isRangeActive) {\\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, false);\\n isRangeActive = !vTokenPosition.liquidityPositions.isEmpty();\\n }\\n}\\n\",\"keccak256\":\"0xeaad27a02472015a705f48c1c4cc42bfbac2380de5206583a8ba2fd8ad62579f\",\"license\":\"BUSL-1.1\"},\"contracts/protocol/clearinghouse/ClearingHouse.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.8.14;\\n\\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\\nimport { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport { PausableUpgradeable } from '@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol';\\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\\n\\nimport { Account } from '../../libraries/Account.sol';\\nimport { AddressHelper } from '../../libraries/AddressHelper.sol';\\nimport { BatchedLoop } from '../../libraries/BatchedLoop.sol';\\nimport { Protocol } from '../../libraries/Protocol.sol';\\nimport { SignedMath } from '../../libraries/SignedMath.sol';\\n\\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\\nimport { IVPoolWrapper } from '../../interfaces/IVPoolWrapper.sol';\\nimport { IOracle } from '../../interfaces/IOracle.sol';\\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\\nimport { IVToken } from '../../interfaces/IVToken.sol';\\n\\nimport { IClearingHouseActions } from '../../interfaces/clearinghouse/IClearingHouseActions.sol';\\nimport { IClearingHouseStructures } from '../../interfaces/clearinghouse/IClearingHouseStructures.sol';\\nimport { IClearingHouseEnums } from '../../interfaces/clearinghouse/IClearingHouseEnums.sol';\\nimport { IClearingHouseOwnerActions } from '../../interfaces/clearinghouse/IClearingHouseOwnerActions.sol';\\nimport { IClearingHouseSystemActions } from '../../interfaces/clearinghouse/IClearingHouseSystemActions.sol';\\n\\nimport { Governable } from '../../utils/Governable.sol';\\nimport { Multicall } from '../../utils/Multicall.sol';\\nimport { ClearingHouseView } from './ClearingHouseView.sol';\\n\\ncontract ClearingHouse is\\n IClearingHouse,\\n Multicall,\\n ClearingHouseView, // contains storage\\n Initializable, // contains storage\\n PausableUpgradeable, // contains storage\\n Governable // contains storage\\n{\\n using AddressHelper for address;\\n using AddressHelper for IERC20;\\n using AddressHelper for IVToken;\\n using SafeERC20 for IERC20;\\n using SignedMath for int256;\\n using SafeCast for uint256;\\n using SafeCast for int256;\\n\\n using Account for Account.Info;\\n using BatchedLoop for BatchedLoop.Info;\\n using Protocol for Protocol.Info;\\n\\n uint16 constant PERC_100_BPS = 10000; // 100% in basis points\\n uint16 constant PERC_10_1E5 = 10000; // 10% in base 1e5\\n\\n modifier onlyRageTradeFactory() {\\n if (rageTradeFactoryAddress != msg.sender) revert NotRageTradeFactory();\\n _;\\n }\\n\\n /**\\n SYSTEM FUNCTIONS\\n */\\n\\n function initialize(\\n address _rageTradeFactoryAddress,\\n address initialGovernance,\\n address initialTeamMultisig,\\n IERC20 _defaultCollateralToken,\\n IOracle _defaultCollateralTokenOracle,\\n IInsuranceFund _insuranceFund,\\n IVQuote _vQuote\\n ) external initializer {\\n rageTradeFactoryAddress = _rageTradeFactoryAddress;\\n protocol.settlementToken = _defaultCollateralToken;\\n insuranceFund = _insuranceFund;\\n\\n protocol.vQuote = _vQuote;\\n\\n _updateCollateralSettings(\\n _defaultCollateralToken,\\n CollateralSettings({ oracle: _defaultCollateralTokenOracle, twapDuration: 60, isAllowedForDeposit: true })\\n );\\n\\n __Governable_init(initialGovernance, initialTeamMultisig);\\n __Pausable_init_unchained();\\n }\\n\\n function registerPool(Pool calldata poolInfo) external onlyRageTradeFactory {\\n uint32 poolId = poolInfo.vToken.truncate();\\n\\n // pool will not be registered twice by the rage trade factory\\n assert(protocol.pools[poolId].vToken.isZero());\\n\\n protocol.pools[poolId] = poolInfo;\\n protocol.poolIds.push(poolId);\\n\\n emit PoolSettingsUpdated(poolId, poolInfo.settings);\\n }\\n\\n /**\\n WITHDRAWAL FUNCTION\\n */\\n function withdrawUSDCToTeamMultisig() external onlyGovernanceOrTeamMultisig {\\n protocol.settlementToken.safeTransfer(teamMultisig(), protocol.settlementToken.balanceOf(address(this)));\\n }\\n\\n /**\\n ADMIN FUNCTIONS\\n */\\n\\n function updateCollateralSettings(IERC20 cToken, CollateralSettings memory collateralSettings)\\n external\\n onlyGovernance\\n {\\n if ((address(collateralSettings.oracle)).isZero()) revert InvalidSetting(0x10);\\n if (collateralSettings.twapDuration > 1 days) revert InvalidSetting(0x11);\\n _updateCollateralSettings(cToken, collateralSettings);\\n }\\n\\n function updatePoolSettings(uint32 poolId, PoolSettings calldata newSettings) external onlyGovernance {\\n protocol.pools[poolId].settings = newSettings;\\n if ((address(newSettings.oracle)).isZero()) revert InvalidSetting(0x20);\\n if (newSettings.twapDuration < 5 minutes || newSettings.twapDuration > 1 days) revert InvalidSetting(0x21);\\n if (newSettings.initialMarginRatioBps > PERC_100_BPS) revert InvalidSetting(0x22);\\n if (newSettings.maintainanceMarginRatioBps > PERC_100_BPS) revert InvalidSetting(0x23);\\n if (newSettings.maxVirtualPriceDeviationRatioBps > (PERC_100_BPS * 2) / 10) revert InvalidSetting(0x24);\\n\\n emit PoolSettingsUpdated(poolId, newSettings);\\n }\\n\\n function updateProtocolSettings(\\n LiquidationParams calldata _liquidationParams,\\n uint256 _removeLimitOrderFee,\\n uint256 _minimumOrderNotional,\\n uint256 _minRequiredMargin\\n ) external onlyGovernance {\\n if (_liquidationParams.rangeLiquidationFeeFraction > PERC_10_1E5) revert InvalidSetting(0x30);\\n if (_liquidationParams.tokenLiquidationFeeFraction > PERC_10_1E5) revert InvalidSetting(0x31);\\n if (_liquidationParams.closeFactorMMThresholdBps > PERC_100_BPS) revert InvalidSetting(0x32);\\n if (_liquidationParams.partialLiquidationCloseFactorBps > PERC_100_BPS) revert InvalidSetting(0x33);\\n if (_liquidationParams.insuranceFundFeeShareBps > PERC_100_BPS) revert InvalidSetting(0x34);\\n if (_liquidationParams.liquidationSlippageSqrtToleranceBps > PERC_100_BPS / 10) revert InvalidSetting(0x35);\\n if (_liquidationParams.maxRangeLiquidationFees > 1000e6) revert InvalidSetting(0x36);\\n if (_liquidationParams.minNotionalLiquidatable > 1000e6) revert InvalidSetting(0x37);\\n if (_removeLimitOrderFee > 1000e6) revert InvalidSetting(0x38);\\n if (_minimumOrderNotional > 1000e6) revert InvalidSetting(0x39);\\n if (_minRequiredMargin > 1000e6) revert InvalidSetting(0x3A);\\n\\n protocol.liquidationParams = _liquidationParams;\\n protocol.removeLimitOrderFee = _removeLimitOrderFee;\\n protocol.minimumOrderNotional = _minimumOrderNotional;\\n protocol.minRequiredMargin = _minRequiredMargin;\\n emit ProtocolSettingsUpdated(\\n _liquidationParams,\\n _removeLimitOrderFee,\\n _minimumOrderNotional,\\n _minRequiredMargin\\n );\\n }\\n\\n function pause(uint256 numberOfPoolsToUpdateInThisTx) external onlyGovernanceOrTeamMultisig whenNotPaused {\\n if (unpauseLoop.isInProgress()) revert CannotPauseIfUnpauseInProgress();\\n\\n bool completed = pauseLoop.iterate({\\n startAt: 0,\\n endBefore: protocol.poolIds.length,\\n batchSize: numberOfPoolsToUpdateInThisTx,\\n execute: _forEachPoolOnPause\\n });\\n\\n if (completed) _pause();\\n }\\n\\n function unpause(uint256 numberOfPoolsToUpdateInThisTx) external onlyGovernanceOrTeamMultisig whenPaused {\\n if (pauseLoop.isInProgress()) revert CannotUnpauseIfPauseInProgress();\\n\\n bool completed = unpauseLoop.iterate({\\n startAt: 0,\\n endBefore: protocol.poolIds.length,\\n batchSize: numberOfPoolsToUpdateInThisTx,\\n execute: _forEachPoolOnUnpause\\n });\\n\\n if (completed) _unpause();\\n }\\n\\n /// @inheritdoc IClearingHouseOwnerActions\\n function withdrawProtocolFee(uint256 numberOfPoolsToUpdateInThisTx) external {\\n withdrawProtocolFeeLoop.iterate({\\n startAt: 0,\\n endBefore: protocol.poolIds.length,\\n batchSize: numberOfPoolsToUpdateInThisTx,\\n execute: _forEachPoolOnWithdrawProtocolFee\\n });\\n }\\n\\n /**\\n USER FUNCTIONS\\n */\\n\\n /// @inheritdoc IClearingHouseActions\\n function createAccount() public whenNotPaused returns (uint256 newAccountId) {\\n newAccountId = numAccounts;\\n numAccounts = newAccountId + 1; // SSTORE\\n\\n Account.Info storage newAccount = accounts[newAccountId];\\n newAccount.owner = msg.sender;\\n newAccount.id = uint96(newAccountId);\\n\\n emit AccountCreated(msg.sender, newAccountId);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function updateMargin(\\n uint256 accountId,\\n uint32 collateralId,\\n int256 amount\\n ) public whenNotPaused {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n _updateMargin(account, collateralId, amount, amount < 0);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function createAccountAndAddMargin(uint32 collateralId, uint256 amount) external returns (uint256 newAccountId) {\\n newAccountId = createAccount();\\n updateMargin(newAccountId, collateralId, int256(amount));\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function updateProfit(uint256 accountId, int256 amount) external whenNotPaused {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n _updateProfit(account, amount, true);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function settleProfit(uint256 accountId) external whenNotPaused {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n account.settleProfit(protocol);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function swapToken(\\n uint256 accountId,\\n uint32 poolId,\\n SwapParams memory swapParams\\n ) external whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n return _swapToken(account, poolId, swapParams, true);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function updateRangeOrder(\\n uint256 accountId,\\n uint32 poolId,\\n LiquidityChangeParams calldata liquidityChangeParams\\n ) external whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\\n _updateAccountPoolPrices(account);\\n return _updateRangeOrder(account, poolId, liquidityChangeParams, true);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function removeLimitOrder(\\n uint256 accountId,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper\\n ) external {\\n _updateAccountPoolPrices(accounts[accountId]);\\n _removeLimitOrder(accountId, poolId, tickLower, tickUpper);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function liquidateLiquidityPositions(uint256 accountId) external {\\n _updateAccountPoolPrices(accounts[accountId]);\\n _liquidateLiquidityPositions(accountId);\\n }\\n\\n /// @inheritdoc IClearingHouseActions\\n function liquidateTokenPosition(uint256 targetAccountId, uint32 poolId) external returns (int256 keeperFee) {\\n _updateAccountPoolPrices(accounts[targetAccountId]);\\n return _liquidateTokenPosition(targetAccountId, poolId);\\n }\\n\\n /**\\n MULTICALL\\n */\\n\\n function multicallWithSingleMarginCheck(uint256 accountId, MulticallOperation[] calldata operations)\\n external\\n returns (bytes[] memory results)\\n {\\n results = new bytes[](operations.length);\\n\\n Account.Info storage account = accounts[accountId];\\n _updateAccountPoolPrices(account);\\n\\n bool checkOwner = false;\\n bool checkProfit = false;\\n bool checkMargin = false;\\n\\n for (uint256 i; i < operations.length; i++) {\\n if (operations[i].operationType == MulticallOperationType.UPDATE_MARGIN) {\\n // ADD_MARGIN\\n (uint32 collateralId, int256 amount) = abi.decode(operations[i].data, (uint32, int256));\\n checkOwner = true;\\n checkMargin = checkMargin || amount < 0;\\n _updateMargin(account, collateralId, amount, false);\\n } else if (operations[i].operationType == MulticallOperationType.UPDATE_PROFIT) {\\n // UPDATE_PROFIT\\n int256 amount = abi.decode(operations[i].data, (int256));\\n _updateProfit(account, amount, false);\\n checkOwner = true;\\n if (amount < 0) {\\n checkProfit = true;\\n checkMargin = true;\\n }\\n } else if (operations[i].operationType == MulticallOperationType.SWAP_TOKEN) {\\n // SWAP_TOKEN\\n (uint32 poolId, SwapParams memory sp) = abi.decode(operations[i].data, (uint32, SwapParams));\\n (int256 vTokenAmountOut, int256 vQuoteAmountOut) = _swapToken(account, poolId, sp, false);\\n results[i] = abi.encode(vTokenAmountOut, vQuoteAmountOut);\\n checkOwner = true;\\n checkMargin = true;\\n } else if (operations[i].operationType == MulticallOperationType.UPDATE_RANGE_ORDER) {\\n // UPDATE_RANGE_ORDER\\n (uint32 poolId, LiquidityChangeParams memory lcp) = abi.decode(\\n operations[i].data,\\n (uint32, LiquidityChangeParams)\\n );\\n (int256 vTokenAmountOut, int256 vQuoteAmountOut) = _updateRangeOrder(account, poolId, lcp, false);\\n results[i] = abi.encode(vTokenAmountOut, vQuoteAmountOut);\\n checkOwner = true;\\n checkMargin = true;\\n } else if (operations[i].operationType == MulticallOperationType.REMOVE_LIMIT_ORDER) {\\n // REMOVE_LIMIT_ORDER\\n (uint32 poolId, int24 tickLower, int24 tickUpper) = abi.decode(\\n operations[i].data,\\n (uint32, int24, int24)\\n );\\n _removeLimitOrder(accountId, poolId, tickLower, tickUpper);\\n } else if (operations[i].operationType == MulticallOperationType.LIQUIDATE_LIQUIDITY_POSITIONS) {\\n // LIQUIDATE_LIQUIDITY_POSITIONS\\n uint32 accountToLiquidate = abi.decode(operations[i].data, (uint32));\\n _liquidateLiquidityPositions(accountToLiquidate);\\n } else if (operations[i].operationType == MulticallOperationType.LIQUIDATE_TOKEN_POSITION) {\\n // LIQUIDATE_TOKEN_POSITION\\n (uint32 accountToLiquidate, uint32 poolId) = abi.decode(operations[i].data, (uint32, uint32));\\n results[i] = abi.encode(_liquidateTokenPosition(accountToLiquidate, poolId));\\n } else {\\n revert InvalidMulticallOperationType(operations[i].operationType);\\n }\\n }\\n\\n // after all the operations are done, check the margin requirements\\n if (checkOwner) _getAccountAndCheckOwner(accountId);\\n if (checkProfit) account.checkIfProfitAvailable(protocol);\\n if (checkMargin) account.checkIfMarginAvailable(true, protocol);\\n\\n return results;\\n }\\n\\n /**\\n INTERNAL HELPERS\\n */\\n\\n function _updateAccountPoolPrices(Account.Info storage account) internal {\\n account.updateAccountPoolPrices(protocol);\\n }\\n\\n function _updateMargin(\\n Account.Info storage account,\\n uint32 collateralId,\\n int256 amount,\\n bool checkMargin\\n ) internal whenNotPaused {\\n Collateral storage collateral = _checkCollateralIdAndGetInfo({\\n collateralId: collateralId,\\n isWithdraw: amount < 0\\n });\\n\\n // delegate call to account library to perform state update and emit events\\n account.updateMargin(collateralId, amount, protocol, checkMargin);\\n\\n // transfer settlement tokens between clearing house and account owner\\n if (amount > 0) {\\n collateral.token.safeTransferFrom(msg.sender, address(this), uint256(amount));\\n } else if (amount < 0) {\\n collateral.token.safeTransfer(msg.sender, uint256(-amount));\\n }\\n }\\n\\n function _updateProfit(\\n Account.Info storage account,\\n int256 amount,\\n bool checkMargin\\n ) internal whenNotPaused {\\n if (amount == 0) revert ZeroAmount();\\n\\n account.updateProfit(amount, protocol, checkMargin);\\n if (amount > 0) {\\n protocol.settlementToken.safeTransferFrom(msg.sender, address(this), uint256(amount));\\n } else {\\n protocol.settlementToken.safeTransfer(msg.sender, uint256(-amount));\\n }\\n }\\n\\n function _updateRangeOrder(\\n Account.Info storage account,\\n uint32 poolId,\\n LiquidityChangeParams memory liquidityChangeParams,\\n bool checkMargin\\n ) internal whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n _checkPoolId(poolId);\\n\\n if (liquidityChangeParams.sqrtPriceCurrent != 0) {\\n _checkSlippage(poolId, liquidityChangeParams.sqrtPriceCurrent, liquidityChangeParams.slippageToleranceBps);\\n }\\n\\n uint256 notionalValueAbs;\\n (vTokenAmountOut, vQuoteAmountOut, notionalValueAbs) = account.liquidityChange(\\n poolId,\\n liquidityChangeParams,\\n protocol,\\n checkMargin\\n );\\n\\n if (notionalValueAbs < protocol.minimumOrderNotional) revert LowNotionalValue(notionalValueAbs);\\n }\\n\\n function _swapToken(\\n Account.Info storage account,\\n uint32 poolId,\\n SwapParams memory swapParams,\\n bool checkMargin\\n ) internal whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\\n _checkPoolId(poolId);\\n\\n (vTokenAmountOut, vQuoteAmountOut) = account.swapToken(poolId, swapParams, protocol, checkMargin);\\n\\n uint256 vQuoteAmountOutAbs = uint256(vQuoteAmountOut.abs());\\n if (vQuoteAmountOutAbs < protocol.minimumOrderNotional) revert LowNotionalValue(vQuoteAmountOutAbs);\\n\\n if (swapParams.sqrtPriceLimit != 0 && !swapParams.isPartialAllowed) {\\n if (\\n !((swapParams.isNotional && vQuoteAmountOut.abs() == swapParams.amount.abs()) ||\\n (!swapParams.isNotional && vTokenAmountOut.abs() == swapParams.amount.abs()))\\n ) revert SlippageBeyondTolerance();\\n }\\n }\\n\\n function _liquidateLiquidityPositions(uint256 accountId) internal whenNotPaused returns (int256) {\\n Account.Info storage account = accounts[accountId];\\n\\n (int256 keeperFee, int256 insuranceFundFee, int256 accountMarketValue) = account.liquidateLiquidityPositions(\\n protocol\\n );\\n\\n int256 accountFee = keeperFee + insuranceFundFee;\\n\\n if (keeperFee <= 0) revert KeeperFeeNotPositive(keeperFee);\\n protocol.settlementToken.safeTransfer(msg.sender, uint256(keeperFee));\\n _transferInsuranceFundFee(insuranceFundFee);\\n\\n emit Account.LiquidityPositionsLiquidated(\\n accountId,\\n msg.sender,\\n accountFee,\\n keeperFee,\\n insuranceFundFee,\\n accountMarketValue\\n );\\n\\n return keeperFee;\\n }\\n\\n function _liquidateTokenPosition(uint256 accountId, uint32 poolId)\\n internal\\n whenNotPaused\\n returns (int256 keeperFee)\\n {\\n Account.Info storage account = accounts[accountId];\\n\\n _checkPoolId(poolId);\\n int256 insuranceFundFee;\\n (keeperFee, insuranceFundFee) = account.liquidateTokenPosition(poolId, protocol);\\n if (keeperFee <= 0) revert KeeperFeeNotPositive(keeperFee);\\n protocol.settlementToken.safeTransfer(msg.sender, uint256(keeperFee));\\n _transferInsuranceFundFee(insuranceFundFee);\\n }\\n\\n function _removeLimitOrder(\\n uint256 accountId,\\n uint32 poolId,\\n int24 tickLower,\\n int24 tickUpper\\n ) internal whenNotPaused returns (uint256 keeperFee) {\\n Account.Info storage account = accounts[accountId];\\n\\n _checkPoolId(poolId);\\n keeperFee = protocol.removeLimitOrderFee;\\n\\n account.removeLimitOrder(poolId, tickLower, tickUpper, keeperFee, protocol);\\n\\n protocol.settlementToken.safeTransfer(msg.sender, keeperFee);\\n }\\n\\n function _transferInsuranceFundFee(int256 insuranceFundFee) internal {\\n if (insuranceFundFee > 0) {\\n protocol.settlementToken.safeTransfer(address(insuranceFund), uint256(insuranceFundFee));\\n } else {\\n insuranceFund.claim(uint256(-insuranceFundFee));\\n }\\n }\\n\\n function _updateCollateralSettings(IERC20 collateralToken, CollateralSettings memory collateralSettings) internal {\\n uint32 collateralId = collateralToken.truncate();\\n\\n // doesn't allow zero address as a collateral token\\n if (collateralToken.isZero()) revert InvalidCollateralAddress(address(0));\\n\\n // doesn't allow owner to change the cToken address when updating settings, once it's truncated previously\\n if (\\n !protocol.collaterals[collateralId].token.isZero() &&\\n !protocol.collaterals[collateralId].token.eq(collateralToken)\\n ) {\\n revert IncorrectCollateralAddress(collateralToken, protocol.collaterals[collateralId].token);\\n }\\n\\n protocol.collaterals[collateralId] = Collateral(collateralToken, collateralSettings);\\n\\n emit CollateralSettingsUpdated(collateralToken, collateralSettings);\\n }\\n\\n /**\\n INTERNAL VIEW METHODS\\n */\\n\\n function _getAccountAndCheckOwner(uint256 accountId) internal view returns (Account.Info storage account) {\\n account = accounts[accountId];\\n if (msg.sender != account.owner) revert AccessDenied(msg.sender);\\n }\\n\\n function _checkCollateralIdAndGetInfo(uint32 collateralId, bool isWithdraw)\\n internal\\n view\\n returns (Collateral storage collateral)\\n {\\n collateral = protocol.collaterals[collateralId];\\n if (collateral.token.isZero()) revert CollateralDoesNotExist(collateralId);\\n // do not check if it is a withdraw operation, so that users can withdraw even if collateral is banned\\n if (!isWithdraw && !collateral.settings.isAllowedForDeposit) revert CollateralNotAllowedForUse(collateralId);\\n }\\n\\n function _checkPoolId(uint32 poolId) internal view {\\n Pool storage pool = protocol.pools[poolId];\\n if (pool.vToken.isZero()) revert PoolDoesNotExist(poolId);\\n if (!pool.settings.isAllowedForTrade) revert PoolNotAllowedForTrade(poolId);\\n }\\n\\n function _checkSlippage(\\n uint32 poolId,\\n uint160 sqrtPriceToCheck,\\n uint16 slippageToleranceBps\\n ) internal view {\\n uint160 sqrtPriceCurrent = protocol.getVirtualCurrentSqrtPriceX96(poolId);\\n uint160 diff = sqrtPriceCurrent > sqrtPriceToCheck\\n ? sqrtPriceCurrent - sqrtPriceToCheck\\n : sqrtPriceToCheck - sqrtPriceCurrent;\\n if (diff > (slippageToleranceBps * sqrtPriceToCheck) / 1e4) {\\n revert SlippageBeyondTolerance();\\n }\\n }\\n\\n /**\\n PRIVATE METHODS\\n */\\n\\n function _forEachPoolOnPause(uint256 index) private {\\n uint32 poolId = protocol.poolIds[index];\\n // account for the funding payment upto this moment before pausing\\n protocol.pools[poolId].vPoolWrapper.updateGlobalFundingState({ useZeroFundingRate: false });\\n }\\n\\n function _forEachPoolOnUnpause(uint256 index) private {\\n uint32 poolId = protocol.poolIds[index];\\n // record the funding payment as zero for the entire duration for which clearing house was paused.\\n protocol.pools[poolId].vPoolWrapper.updateGlobalFundingState({ useZeroFundingRate: true });\\n }\\n\\n function _forEachPoolOnWithdrawProtocolFee(uint256 index) private {\\n uint32 poolId = protocol.poolIds[index];\\n uint256 feeCollected = protocol.pools[poolId].vPoolWrapper.collectAccruedProtocolFee();\\n // if any protocol fee was collected then transfer to multisig\\n if (feeCollected != 0) {\\n protocol.settlementToken.safeTransfer(teamMultisig(), feeCollected);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb53649e13bf04fa300a5572b1c4f6ec444e52dd14802a9f4d354912d2574b609\",\"license\":\"BUSL-1.1\"},\"contracts/protocol/clearinghouse/ClearingHouseStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.8.14;\\n\\nimport { Account } from '../../libraries/Account.sol';\\nimport { BatchedLoop } from '../../libraries/BatchedLoop.sol';\\nimport { Protocol } from '../../libraries/Protocol.sol';\\n\\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\\nimport { IOracle } from '../../interfaces/IOracle.sol';\\n\\nabstract contract ClearingHouseStorage {\\n // rest slots reserved for any states from inheritance in future\\n uint256[100] private _emptySlots1;\\n\\n // at slot # 100\\n Protocol.Info internal protocol;\\n\\n uint256 public numAccounts;\\n mapping(uint256 => Account.Info) accounts;\\n\\n address public rageTradeFactoryAddress;\\n IInsuranceFund public insuranceFund;\\n\\n // progress index, used for performing for loop\\n // over an unbounded array in multiple txs\\n BatchedLoop.Info internal pauseLoop;\\n BatchedLoop.Info internal unpauseLoop;\\n BatchedLoop.Info internal withdrawProtocolFeeLoop;\\n\\n // reserved for adding slots in future\\n uint256[100] private _emptySlots2;\\n}\\n\",\"keccak256\":\"0x30e24a3572f24a033cc9ed78865bd8406191ddfbb70cc20019b68503c4d1a624\",\"license\":\"BUSL-1.1\"},\"contracts/protocol/clearinghouse/ClearingHouseView.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.8.14;\\n\\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\\nimport { IClearingHouseView } from '../../interfaces/clearinghouse/IClearingHouseView.sol';\\n\\nimport { Account } from '../../libraries/Account.sol';\\nimport { Protocol } from '../../libraries/Protocol.sol';\\n\\nimport { ClearingHouseStorage } from './ClearingHouseStorage.sol';\\n\\nimport { Extsload } from '../../utils/Extsload.sol';\\n\\nabstract contract ClearingHouseView is IClearingHouse, ClearingHouseStorage, Extsload {\\n using Account for Account.Info;\\n using Protocol for Protocol.Info;\\n\\n /// @inheritdoc IClearingHouseView\\n function getAccountMarketValueAndRequiredMargin(uint256 accountId, bool isInitialMargin)\\n public\\n view\\n returns (int256 marketValue, int256 requiredMargin)\\n {\\n (marketValue, requiredMargin) = accounts[accountId].getAccountValueAndRequiredMargin(isInitialMargin, protocol);\\n }\\n\\n /// @inheritdoc IClearingHouseView\\n function getAccountNetProfit(uint256 accountId) public view returns (int256 accountNetProfit) {\\n accountNetProfit = accounts[accountId].getAccountPositionProfits(protocol);\\n }\\n\\n /// @inheritdoc IClearingHouseView\\n function getAccountNetTokenPosition(uint256 accountId, uint32 poolId) public view returns (int256 netPosition) {\\n return accounts[accountId].getNetPosition(poolId, protocol);\\n }\\n\\n /// @inheritdoc IClearingHouseView\\n function getRealTwapPriceX128(uint32 poolId) public view returns (uint256 realPriceX128) {\\n realPriceX128 = protocol.getCachedRealTwapPriceX128(poolId);\\n }\\n\\n /// @inheritdoc IClearingHouseView\\n function getVirtualTwapPriceX128(uint32 poolId) public view returns (uint256 virtualPriceX128) {\\n virtualPriceX128 = protocol.getCachedVirtualTwapPriceX128(poolId);\\n }\\n}\\n\",\"keccak256\":\"0xbec5c93cfdf81646e4539224af0b4cb4922ab3d2e6e2523534903fd2fa6dbc11\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Extsload.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.5.0;\\n\\nimport { IExtsload } from '../interfaces/IExtsload.sol';\\n\\n/// @notice Allows the inheriting contract make it's state accessable to other contracts\\n/// https://ethereum-magicians.org/t/extsload-opcode-proposal/2410/11\\nabstract contract Extsload is IExtsload {\\n function extsload(bytes32 slot) external view returns (bytes32 val) {\\n assembly {\\n val := sload(slot)\\n }\\n }\\n\\n function extsload(bytes32[] memory slots) external view returns (bytes32[] memory) {\\n assembly {\\n let end := add(0x20, add(slots, mul(mload(slots), 0x20)))\\n for {\\n let pointer := add(slots, 32)\\n } lt(pointer, end) {\\n\\n } {\\n let value := sload(mload(pointer))\\n mstore(pointer, value)\\n pointer := add(pointer, 0x20)\\n }\\n }\\n\\n return slots;\\n }\\n}\\n\",\"keccak256\":\"0xb74368b2d34810fd8f3586adfc2884fde340a89eba265456b284278ede44eed1\",\"license\":\"MIT\"},\"contracts/utils/Governable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.4;\\n\\nimport { ContextUpgradeable } from '@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol';\\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\\n\\nimport { IGovernable } from '../interfaces/IGovernable.sol';\\n\\n/// @title Governable module that exposes onlyGovernance and onlyGovernanceOrTeamMultisig modifiers\\n/// @notice Copied and modified from @openzeppelin/contracts/access/Ownable.sol\\nabstract contract Governable is IGovernable, Initializable, ContextUpgradeable {\\n address private _governance;\\n address private _teamMultisig;\\n address private _governancePending;\\n address private _teamMultisigPending;\\n\\n event GovernanceTransferred(address indexed previousGovernance, address indexed newGovernance);\\n event TeamMultisigTransferred(address indexed previousTeamMultisig, address indexed newTeamMultisig);\\n event GovernancePending(address indexed previousGovernancePending, address indexed newGovernancePending);\\n event TeamMultisigPending(address indexed previousTeamMultisigPending, address indexed newTeamMultisigPending);\\n\\n error Unauthorised();\\n error ZeroAddress();\\n\\n /// @notice Initializes the contract setting the deployer as the initial governance and team multisig.\\n constructor() {\\n __Governable_init();\\n }\\n\\n /// @notice Useful to proxy contracts for initializing\\n function __Governable_init() internal initializer {\\n __Context_init();\\n address msgSender = _msgSender();\\n __Governable_init(msgSender, msgSender);\\n }\\n\\n /// @notice Useful to proxy contracts for initializing with custom addresses\\n /// @param initialGovernance the initial governance address\\n /// @param initialTeamMultisig the initial teamMultisig address\\n function __Governable_init(address initialGovernance, address initialTeamMultisig) internal initializer {\\n _governance = initialGovernance;\\n emit GovernanceTransferred(address(0), initialGovernance);\\n\\n _teamMultisig = initialTeamMultisig;\\n emit TeamMultisigTransferred(address(0), initialTeamMultisig);\\n }\\n\\n /// @notice Returns the address of the current governance.\\n\\n function governance() public view virtual returns (address) {\\n return _governance;\\n }\\n\\n /// @notice Returns the address of the current governance.\\n function governancePending() public view virtual returns (address) {\\n return _governancePending;\\n }\\n\\n /// @notice Returns the address of the current team multisig.transferTeamMultisig\\n function teamMultisig() public view virtual returns (address) {\\n return _teamMultisig;\\n }\\n\\n /// @notice Returns the address of the current team multisig.transferTeamMultisig\\n function teamMultisigPending() public view virtual returns (address) {\\n return _teamMultisigPending;\\n }\\n\\n /// @notice Throws if called by any account other than the governance.\\n modifier onlyGovernance() {\\n if (governance() != _msgSender()) revert Unauthorised();\\n _;\\n }\\n\\n /// @notice Throws if called by any account other than the governance or team multisig.\\n modifier onlyGovernanceOrTeamMultisig() {\\n if (teamMultisig() != _msgSender() && governance() != _msgSender()) revert Unauthorised();\\n _;\\n }\\n\\n /// @notice Initiates governance transfer to a new account (`newGovernancePending`).\\n /// @param newGovernancePending the new governance address\\n function initiateGovernanceTransfer(address newGovernancePending) external virtual onlyGovernance {\\n emit GovernancePending(_governancePending, newGovernancePending);\\n _governancePending = newGovernancePending;\\n }\\n\\n /// @notice Completes governance transfer, on being called by _governancePending.\\n function acceptGovernanceTransfer() external virtual {\\n if (_msgSender() != _governancePending) revert Unauthorised();\\n\\n emit GovernanceTransferred(_governance, _governancePending);\\n _governance = _governancePending;\\n _governancePending = address(0);\\n }\\n\\n /// @notice Initiates teamMultisig transfer to a new account (`newTeamMultisigPending`).\\n /// @param newTeamMultisigPending the new team multisig address\\n function initiateTeamMultisigTransfer(address newTeamMultisigPending)\\n external\\n virtual\\n onlyGovernanceOrTeamMultisig\\n {\\n emit TeamMultisigPending(_teamMultisigPending, newTeamMultisigPending);\\n _teamMultisigPending = newTeamMultisigPending;\\n }\\n\\n /// @notice Completes teamMultisig transfer, on being called by _teamMultisigPending.\\n function acceptTeamMultisigTransfer() external virtual {\\n if (_msgSender() != _teamMultisigPending) revert Unauthorised();\\n\\n emit TeamMultisigTransferred(_teamMultisig, _teamMultisigPending);\\n _teamMultisig = _teamMultisigPending;\\n _teamMultisigPending = address(0);\\n }\\n}\\n\",\"keccak256\":\"0x273cce59e410a4ae955fc40f202c937d2aa5bcef929c7bcd7a75ed446a12ac52\",\"license\":\"MIT\"},\"contracts/utils/Multicall.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.7.6;\\npragma abicoder v2;\\n\\nimport { IMulticall } from '@uniswap/v3-periphery/contracts/interfaces/IMulticall.sol';\\n\\n/// @title Multicall\\n/// @notice Enables calling multiple methods in a single call to the contract\\nabstract contract Multicall is IMulticall {\\n /// @inheritdoc IMulticall\\n function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) {\\n results = new bytes[](data.length);\\n for (uint256 i = 0; i < data.length; i++) {\\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\\n\\n if (!success) {\\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\\n if (result.length < 68) revert();\\n assembly {\\n result := add(result, 0x04)\\n }\\n revert(abi.decode(result, (string)));\\n }\\n\\n results[i] = result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd44030ded009dd01cd697c036595249f3c49355ceb8d37eaa2ea546eb7375f7b\",\"license\":\"GPL-2.0-or-later\"}},\"version\":1}", + "bytecode": "0x6080604052346200011b5761013d805460ff8160081c1690816000146200010c57506200002e303b1562000120565b159081620000f6575b5460ff8160081c1680156200009d57156200008e57506200005a303b1562000120565b62000066333362000184565b6200007c575b604051615cf89081620002098239f35b61013d805461ff00191690556200006c565b60ff6200005a91161562000120565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b61013d805461ffff191661010117905562000037565b60ff6200002e91161562000120565b600080fd5b156200012857565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b6101a280546001600160a01b039283166001600160a01b0319918216811790925560405190936000937f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb29385939290847f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808186a31694856101a391825416179055a356fe60806040526004361015610013575b600080fd5b60003560e01c806304a6f264146103335780630df181ea1461032a5780631340155114610321578063136439dd146103185780631e2eaeaf1461030f5780632a90b8da146103065780633562490c146102fd57806335876476146102f45780633d0aea3d146102eb5780633d48e983146102e25780633d56a35e146102d95780633ffe794c146102d057806340c4f69b146102c7578063424cd833146102be57806343afafba146102b5578063569634d3146102ac5780635aa6e675146102a35780635c975abb1461029a5780636a486482146102915780636ae7323014610288578063706bdd251461027f5780637cc2f4f5146102765780637d2efe071461026d57806383d778eb146102645780638ce25a931461025b5780638f24ab11146102525780638f8022bc146102495780639cd1be58146102405780639dca362f14610237578063a05c8baf1461022e578063ac9650d814610225578063b79023031461021c578063c7505c1514610213578063ce4c18de1461020a578063dbc0c08514610201578063dbd035ff146101f8578063e3d41c18146101ef578063e450f6f4146101e6578063e67ed1df146101dd5763fabc1cbc146101d557600080fd5b61000e6126ca565b5061000e6125f1565b5061000e61249c565b5061000e612408565b5061000e612371565b5061000e6122e6565b5061000e6122be565b5061000e612124565b5061000e6120fc565b5061000e61201b565b5061000e611d9b565b5061000e611d5b565b5061000e611c24565b5061000e611bab565b5061000e6119c2565b5061000e6119a3565b5061000e611757565b5061000e611598565b5061000e61153f565b5061000e611501565b5061000e61145a565b5061000e611381565b5061000e61135c565b5061000e611333565b5061000e611305565b5061000e6112bd565b5061000e611142565b5061000e610c2e565b5061000e610a24565b5061000e6109fc565b5061000e61092c565b5061000e61089e565b5061000e6106a1565b5061000e6105f5565b5061000e610582565b5061000e610562565b5061000e61045e565b5061000e610435565b5061000e610370565b5061000e610347565b600091031261000e57565b503461000e57600060031936011261000e5760206001600160a01b036101a55416604051908152f35b503461000e57600060206003193601126104325761039460ff610170541615613585565b61039f600435615896565b6103a881613cab565b81733fab135e76c5c0e85a60bf50f100c8cd912f7e5691823b1561042e576044604051809481937feaf393260000000000000000000000000000000000000000000000000000000083526004830152606460248301525af48015610421575b610412575b50604051f35b61041b906107a1565b3861040c565b610429612f42565b610407565b5080fd5b80fd5b503461000e57600060031936011261000e5760206001600160a01b036101a45416604051908152f35b503461000e57602060031936011261000e576001600160a01b03806101a354163314159081610552575b506105285761017061049e60ff82541615613585565b60d7546104fe576104b36004356066546135f8565b6104ba575b005b600160ff1982546104ce60ff821615613585565b161790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b60046040517fd2067f43000000000000000000000000000000000000000000000000000000008152fd5b60046040517fd7a2ae6a000000000000000000000000000000000000000000000000000000008152fd5b6101a25416331415905038610488565b503461000e57602060031936011261000e57602060043554604051908152f35b503461000e57600060031936011261000e576101a48054906001600160a01b0390818316803303610528576000936101a2805492806040519685167f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808989a36001600160a01b0319809416179055169055f35b503461000e57600060031936011261000e576101a58054906001600160a01b0390818316803303610528576000936101a3805492806040519685167f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb28989a36001600160a01b0319809416179055169055f35b6001600160a01b0381160361000e57565b610124359061068782610668565b565b60e4359061068782610668565b359061068782610668565b503461000e5760e060031936011261000e576004356106bf81610668565b6107396024356106ce81610668565b6044356106da81610668565b6064356106e681610668565b608435906106f382610668565b60a4359261070084610668565b60c4359461070d86610668565b61013d5460ff8160081c16908160001461077d575061072d303b1561279e565b1597886107505761280f565b61073f57005b6104b861013d61ff00198154169055565b61076561013d61010061ff0019825416179055565b61077861013d600160ff19825416179055565b61280f565b60ff61072d91161561279e565b50634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116107b557604052565b6107bd61078a565b604052565b60a0810190811067ffffffffffffffff8211176107b557604052565b6040810190811067ffffffffffffffff8211176107b557604052565b6060810190811067ffffffffffffffff8211176107b557604052565b90601f601f19910116810190811067ffffffffffffffff8211176107b557604052565b60405190610687826107de565b63ffffffff81160361000e57565b8015150361000e57565b60e4359061068782610854565b610104359061068782610854565b60a4359061068782610854565b60c4359061068782610854565b359061068782610854565b503461000e57608060031936011261000e576004356108bc81610668565b606060231936011261000e576040516104b8916060820167ffffffffffffffff81118382101761091f575b6040526024356108f681610668565b825260443561090481610846565b602083015260643561091581610854565b60408301526131c5565b61092761078a565b6108e7565b503461000e57600060031936011261000e576001600160a01b03806101a3541633811415806109ed575b610528576067546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526104b89390929116602083602481845afa9283156109e0575b6000936109b0575b50612f4f565b6109d291935060203d81116109d9575b6109ca8183610816565b810190612f33565b91386109aa565b503d6109c0565b6109e8612f42565b6109a2565b5033826101a254161415610956565b503461000e57600060031936011261000e5760206001600160a01b0360d45416604051908152f35b503461000e5761014060031936011261000e576001600160a01b038060d454163303610af957610a7d63ffffffff600435610a5e81610668565b1691826000526064602052604060002054166001600160a01b03161590565b15610ae357610ade81610ac9610ac47f4182acc9c169391ef7e765eb446fc15c9d49bc73060c678bf4c424a5c0dbdbcb9463ffffffff166000526064602052604060002090565b612bdc565b610ad281612d72565b60405191829182612e0b565b0390a1005b634e487b7160e01b600052600160045260246000fd5b60046040517f85734f31000000000000000000000000000000000000000000000000000000008152fd5b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b918091926000905b828210610b74575011610b6d575050565b6000910152565b91508060209183015181860152018291610b5c565b90601f19601f602093610ba781518092818752878088019101610b54565b0116010190565b602080820190808352835180925260408301928160408460051b8301019501936000915b848310610be25750505050505090565b9091929394958480610c1e837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a51610b89565b9801930193019194939290610bd2565b503461000e5760408060031936011261000e57600480359160243567ffffffffffffffff811161000e57610c659036908401610b23565b610c71819492946139f5565b93610c868660005260d3602052604060002090565b95610c9087613cab565b60008781938295835b818110610e0b5750505050610dfb575b50610d64575b610cc5575b815180610cc18582610bae565b0390f35b733fab135e76c5c0e85a60bf50f100c8cd912f7e5690813b1561000e5782517f998c53350000000000000000000000000000000000000000000000000000000081529081019485526001602086015260646040860152610cc19490916000918391908290819060600103915af48015610d57575b15610cb45780610d4b610d51926107a1565b8061033c565b38610cb4565b610d5f612f42565b610d39565b733fab135e76c5c0e85a60bf50f100c8cd912f7e56803b1561000e576000845180927f651524ed0000000000000000000000000000000000000000000000000000000082528180610dc58b8983016020606491939293604081019481520152565b03915af48015610dee575b610ddb575b50610caf565b80610d4b610de8926107a1565b38610dd5565b610df6612f42565b610dd0565b610e0490615896565b5038610ca9565b9091929693610e23610e1e838587613a3e565b613ab5565b610e2c81613aa3565b610e84575080610e6c610e5b610e53610e49610e71958789613a3e565b6020810190613ae0565b810190613c8c565b906001978015610e7a575b9a614ab5565b6135e8565b908a9291610c99565b5060008212610e66565b939650610e95610e1e828486613a3e565b93610e9f85613aa3565b6001948503610eee5750610ec2610eba610e49838587613a3e565b810190613c7d565b93610ecd858d614c11565b6000819512610ee1575b50610e71906135e8565b9650869550610e71610ed7565b6002610f01610e1e8486889c969c613a3e565b610f0a81613aa3565b03610f8b575050610f5d610f6b610f22888486613a3e565b610f468d610f40610f3860209485810190613ae0565b810190613bf7565b91614f24565b8c5192830191825260208201529092839160400190565b03601f198101835282610816565b610f75878b613b7d565b52610f80868a613b7d565b50610e7183966135e8565b6003610f9b610e1e8a8688613a3e565b610fa481613aa3565b03610fe0575050610f5d610f6b610fbc888486613a3e565b610f468d610fda610fd260209485810190613ae0565b810190613bd2565b91614cf8565b93509587610ff2610e1e838587613a3e565b610ffb81613aa3565b0361102d5780611027611020611018610e49610e71958789613a3e565b810190613b9f565b9189615475565b506135e8565b600561103d610e1e838587613a3e565b61104681613aa3565b0361107c578061102761107761106e611066610e49610e7196888a613a3e565b8101906114e9565b63ffffffff1690565b61517b565b600661108c610e1e838587613a3e565b61109581613aa3565b036110fc57806110a9610e71928486613a3e565b6110e76110d563ffffffff6110ce6110c660209586810190613ae0565b810190613b31565b9116615344565b8c519283019081528290602001610f5d565b6110f1828d613b7d565b52611027818c613b7d565b61110f610e1e61113e928a948c96613a3e565b92519283927f62c9ca420000000000000000000000000000000000000000000000000000000084528301613ac2565b0390fd5b503461000e5760208060031936011261000e5760665460d854600492833582156112b4575b600090806112915750508293915b84811061119257505050810361118d5750600060d855005b60d855005b806000836111ea6111de60026111d063ffffffff6111b261123399612d24565b90549060031b1c1663ffffffff166000526064602052604060002090565b01546001600160a01b031690565b6001600160a01b031690565b86604051809481937f5e622abc0000000000000000000000000000000000000000000000000000000083525af1908115611284575b600091611267575b508061123857506135e8565b611175565b6112619061124e6067546001600160a01b031690565b6001600160a01b036101a3541690612f4f565b38611027565b61127e9150843d86116109d9576109ca8183610816565b38611227565b61128c612f42565b61121f565b61129b90846135d0565b9050838110156112ad575b9391611175565b50826112a6565b60009250611167565b503461000e57604060031936011261000e5760206112fd6024356004356112e382610846565b8060005260d384526112f86040600020613cab565b615344565b604051908152f35b503461000e57602060031936011261000e576104b86004358060005260d36020526110776040600020613cab565b503461000e57600060031936011261000e5760206001600160a01b036101a25416604051908152f35b503461000e57600060031936011261000e57602060ff61017054166040519015158152f35b503461000e57604060031936011261000e57610cc16024356113a281610846565b60043560005260d360205263ffffffff604060002091604051927f7188a1ed000000000000000000000000000000000000000000000000000000008452600484015216602482015260646044820152602081606481733fab135e76c5c0e85a60bf50f100c8cd912f7e565af490811561144d575b60009161142f575b506040519081529081906020820190565b611447915060203d81116109d9576109ca8183610816565b3861141e565b611455612f42565b611416565b503461000e57602060031936011261000e5760043561147881610668565b6001600160a01b03806101a35416331415806114da575b610528576000916101a5906001600160a01b0319838354921691826040519582167f9b068aae3039a2512c2f13bffb5fd9d95b1895b276b5c7ddf1d4fa24ec3686588888a316179055f35b5033816101a25416141561148f565b9081602091031261000e57356114fe81610846565b90565b503461000e57602060031936011261000e5760206112fd60043561152481610846565b615b62565b8060020b0361000e57565b359061068782611529565b503461000e57608060031936011261000e576104b860043560243561156381610846565b6044359061157082611529565b6064359261157d84611529565b8060005260d36020526115936040600020613cab565b615475565b503461000e57606060031936011261000e576024356115b681610846565b604435610170906115cb60ff83541615613585565b6115d6600435615896565b916115e083613cab565b6000936115f460ff86851293541615613585565b846115ff83836158e1565b94733fab135e76c5c0e85a60bf50f100c8cd912f7e56803b156116ee5760405163f5a284a160e01b8152600481019290925263ffffffff93909316602482015260448101859052606480820152831515608482015291829060a49082905af480156116e1575b6116ce575b5083821315611696575061168861169192546001600160a01b031690565b30903390614ba3565b604051f35b6116a2575b5050604051f35b6116bf6116b96116c793546001600160a01b031690565b916145d7565b903390612f4f565b388061169b565b80610d4b6116db926107a1565b3861166a565b6116e9612f42565b611665565b8280fd5b60431960a091011261000e576040519061170b826107c2565b81604435815260643561171d81610668565b602082015260843561172e81610854565b604082015260a43561173f81610854565b6060820152608060c4359161175383610854565b0152565b503461000e5760e060031936011261000e5760243561177581610846565b61177e366116f2565b809161017061179160ff82541615613585565b6117b360ff6117a1600435615896565b926117ab84613cab565b541615613585565b6117bc8261598c565b60409182916117f7835195869384937f140cf61e00000000000000000000000000000000000000000000000000000000855260048501615114565b0381733fab135e76c5c0e85a60bf50f100c8cd912f7e565af4928315611996575b6000928394611961575b5061182c846145f6565b606c54811061192f57506001600160a01b0361185260208301516001600160a01b031690565b16151580611919575b611872575b50519081526020810191909152604090f35b818101906118808251151590565b91826118fd575b82156118c4575b50501561189b5738611860565b600490517f07a1db07000000000000000000000000000000000000000000000000000000008152fd5b51909150156118d2565b1590565b90816118e1575b50388061188e565b90506118f66118ef846145f6565b91516145f6565b14386118d9565b9150611908856145f6565b61191282516145f6565b1491611887565b5061192a6118ce6060830151151590565b61185b565b82517f256d6b9a0000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b909350816119859293503d841161198f575b61197d8183610816565b8101906150fe565b9190919238611822565b503d611973565b61199e612f42565b611818565b503461000e57600060031936011261000e57602060d254604051908152f35b503461000e5761010060031936011261000e5760048035906119e382610846565b60e060231936011261000e576001600160a01b036101a254163303611b8357611a276003611a218463ffffffff166000526064602052604060002090565b01612a64565b611a42611a356111de612a4b565b6001600160a01b03161590565b611b655763ffffffff61012c81611a57612a26565b1610908115611b4f575b50611b305761ffff6127108082611a766129f8565b1611611b1257611a8e611a87612a04565b61ffff1690565b11611af4576107d090611a9f612a10565b1611611ad5576040517f4182acc9c169391ef7e765eb446fc15c9d49bc73060c678bf4c424a5c0dbdbcb9080610ade8582612eaf565b604051636a098dd160e11b815260249181019182529081906020010390fd5b604051636a098dd160e11b8152602381840190815281906020010390fd5b604051636a098dd160e11b8152602281850190815281906020010390fd5b604051636a098dd160e11b815260219181019182529081906020010390fd5b620151809150611b5d612a26565b161138611a61565b604051636a098dd160e11b8152602091810182815290918291010390fd5b6040517fd7a2ae6a000000000000000000000000000000000000000000000000000000008152fd5b503461000e57602060031936011261000e57600435611bc981610668565b6001600160a01b03806101a254163303610528576000916101a4906001600160a01b0319838354921691826040519582167f8c405decc72a19ef328c92989ce6db4e4a498e1c246413fd60997a3051ba5cff8888a316179055f35b503461000e57604060031936011261000e57602435610170611c4a60ff82541615613585565b611c5a60ff6117a1600435615896565b8115611d3157733fab135e76c5c0e85a60bf50f100c8cd912f7e56803b1561000e576040517fd25c4a6f000000000000000000000000000000000000000000000000000000008152600481019290925260248201839052606460448301819052600190830152600090829060849082905af48015611d24575b611d11575b506000811315611cf8576104b8906116886067546001600160a01b031690565b6104b8906116bf6116b96067546001600160a01b031690565b80610d4b611d1e926107a1565b38611cd8565b611d2c612f42565b611cd3565b60046040517f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b503461000e57600060031936011261000e5760206112fd613848565b60031961010091011261000e57600490565b60431961010091011261000e57604490565b503461000e5761016060031936011261000e57611db736611d77565b610104356101243591610144356001600160a01b036101a254163303610528576127109361ffff8581611de986612a1c565b16116120025785611dff611a8760208701612a1c565b11611fe95760409580611e16611a87898801612a1c565b11611fd15780611e2b611a8760608801612a1c565b11611fb957611e3f611a8760808701612a1c565b11611fa1576103e890611e5460a08601612a1c565b1611611f8957633b9aca008067ffffffffffffffff611e7560c0870161327d565b1611611f715780611e98611e8b60e0870161327d565b67ffffffffffffffff1690565b11611f5957808511611f4157808211611f29578211611f115791611f0b60009594927f697aec6e94e319190380ab0f1f10018d81b64da2479eb874be92c9a733e0a83794611ee584613287565b611eee85606b55565b611ef781606c55565b611f0082606a55565b865194859485613499565b0390a151f35b8451636a098dd160e11b8152603a6004820152602490fd5b8551636a098dd160e11b815260396004820152602490fd5b8551636a098dd160e11b815260386004820152602490fd5b8551636a098dd160e11b815260376004820152602490fd5b8551636a098dd160e11b815260366004820152602490fd5b8451636a098dd160e11b815260356004820152602490fd5b8551636a098dd160e11b815260346004820152602490fd5b8651636a098dd160e11b815260336004820152602490fd5b8651636a098dd160e11b815260326004820152602490fd5b604051636a098dd160e11b815260316004820152602490fd5b604051636a098dd160e11b815260306004820152602490fd5b50602060031936011261000e576004803567ffffffffffffffff811161000e576120489036908301610b23565b90612052826139f5565b9160005b81811061206b5760405180610cc18682610bae565b600080612079838587615c2b565b6040939161208b855180938193615c55565b0390305af490612099613144565b918290156120c2575050906120bd916120b28287613b7d565b526110278186613b7d565b612056565b826044899394511061000e5761113e91836120e7920160248091518301019101615c63565b925192839262461bcd60e51b84528301613174565b503461000e57600060031936011261000e5760206001600160a01b0360d55416604051908152f35b503461000e5761014060031936011261000e5760243561214381610846565b606061214e36611d89565b916101709261216160ff85541615613585565b61218e60ff612185612174600435615896565b9361217e85613cab565b3690613938565b95541615613585565b6121978261598c565b828401516001600160a01b03168061229e575b506121e260405194859384937fc27789d100000000000000000000000000000000000000000000000000000000855260048501614e12565b0381733fab135e76c5c0e85a60bf50f100c8cd912f7e565af48015612291575b6000908192829161225d575b50606c54811061222a5750604080519182526020820192909252f35b6040517f256d6b9a0000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b915050612281915060603d811161228a575b6122798183610816565b810190614dea565b9190913861220e565b503d61226f565b612299612f42565b612202565b6122b8906122b1608087015161ffff1690565b9084615a69565b386121aa565b503461000e57602060031936011261000e5760206112fd6004356122e181610846565b615bc0565b503461000e57600060031936011261000e5760206001600160a01b036101a35416604051908152f35b60209067ffffffffffffffff8111612329575b60051b0190565b61233161078a565b612322565b6020908160408183019282815285518094520193019160005b82811061235d575050505090565b83518552938101939281019260010161234f565b503461000e5760208060031936011261000e5760043567ffffffffffffffff811161000e573660238201121561000e578060040135906123b08261230f565b916123be6040519384610816565b80835260248484019160051b8301019136831161000e57602401905b8282106123f957610cc16123ed85615c02565b60405191829182612336565b813581529084019084016123da565b503461000e57602060031936011261000e5760043560005260d3602052610cc16040600020604051907fc4b22b86000000000000000000000000000000000000000000000000000000008252600482015260646024820152602081604481733fab135e76c5c0e85a60bf50f100c8cd912f7e565af490811561144d5760009161142f57506040519081529081906020820190565b503461000e57604060031936011261000e576004356124ba81610846565b602435906124c6613848565b90610170926124d960ff85541615613585565b6124e283615896565b936124ec85613cab565b6124fe60ff6000841292541615613585565b61250881846158e1565b92733fab135e76c5c0e85a60bf50f100c8cd912f7e5690813b1561000e5760405163f5a284a160e01b8152600481019790975263ffffffff166024870152604486018390526064808701528115156084870152610cc19590600090829060a49082905af480156125e4575b6125d1575b5060008213156125a7575061168861259792546001600160a01b031690565b6040519081529081906020820190565b6125b3575b5050612597565b6116bf6116b96125ca93546001600160a01b031690565b38806125ac565b80610d4b6125de926107a1565b38612578565b6125ec612f42565b612573565b503461000e5760408060031936011261000e5760243561261081610854565b60043560005260d360205281600020908251917f0c6d7f34000000000000000000000000000000000000000000000000000000008352600483015215156024820152606460448201528181606481733fab135e76c5c0e85a60bf50f100c8cd912f7e565af49182156126bd575b60009182936126985750519081526020810191909152604090f35b816126b5929450610cc193503d851161198f5761197d8183610816565b929091611860565b6126c5612f42565b61267d565b503461000e57602060031936011261000e576001600160a01b03806101a35416331415908161278e575b506105285761017061270960ff8254166137fd565b60d6546127645761271e600435606654613712565b61272457005b60ff19815461273560ff82166137fd565b1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b60046040517ffc23b9cd000000000000000000000000000000000000000000000000000000008152fd5b6101a254163314159050386126f4565b156127a557565b608460405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b93916128a17f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb2936000958694986001600160a01b039a8b8092816001600160a01b03199c168c60d454161760d4558185168c6067541617606755168a60d554161760d55516886068541617606855896040519261288b846107fa565b168252603c6020830152600160408301526156ce565b61013d9680885460ff8160081c169081861461295957506128c3303b1561279e565b15978861292c575b16916101a2838882541617905560405192847f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808186a31694856101a391825416179055a361291d575b50610687612966565b61ff0019815416905538612914565b61294161013d61010061ff0019825416179055565b61295461013d600160ff19825416179055565b6128cb565b60ff6128c391161561279e565b60ff61013d5460081c16156129825761017060ff198154169055565b608460405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152fd5b61ffff81160361000e57565b6024356114fe816129ec565b6044356114fe816129ec565b6064356114fe816129ec565b356114fe816129ec565b6084356114fe81610846565b60e4356114fe81610854565b610104356114fe81610854565b60e4356114fe81610668565b610124356114fe81610668565b61068790612a89602435612a77816129ec565b829061ffff1661ffff19825416179055565b612ab2604435612a98816129ec565b825463ffff0000191660109190911b63ffff000016178255565b612adf606435612ac1816129ec565b825465ffff00000000191660209190911b65ffff0000000016178255565b608435612aeb81610846565b69ffffffff0000000000001969ffffffff00000000000083549260301b169116178155612b5960a435612b1d81610854565b82547fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff1690151560501b6aff0000000000000000000016178255565b612ba560c435612b6881610854565b82547fffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffff1690151560581b6bff000000000000000000000016178255565b60e43590612bb282610668565b906bffffffffffffffffffffffff6bffffffffffffffffffffffff1983549260601b169116179055565b600361068791612c0d600435612bf181610668565b82906001600160a01b03166001600160a01b0319825416179055565b612c3b602435612c1c81610668565b60018301906001600160a01b03166001600160a01b0319825416179055565b612c69604435612c4a81610668565b60028301906001600160a01b03166001600160a01b0319825416179055565b01612c79606435612a77816129ec565b612c88608435612a98816129ec565b612c9760a435612ac1816129ec565b60c435612ca381610846565b69ffffffff0000000000001969ffffffff00000000000083549260301b169116178155612cd1612b1d612a32565b612cdc612b68612a3e565b612ce4612a57565b6bffffffffffffffffffffffff6bffffffffffffffffffffffff1983549260601b169116179055565b50634e487b7160e01b600052603260045260246000fd5b90606654821015612d65575b6066600052601c8260031c7f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354019260021b1690565b612d6d612d0d565b612d30565b6066549068010000000000000000821015612df3575b6001820180606655821015612de6575b60666000528160031c7f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354019160e083549160051b169163ffffffff9283811b93849216901b16911916179055565b612dee612d0d565b612d98565b612dfb61078a565b612d88565b3590610687826129ec565b63ffffffff9182168152610100810192916106879190606435612e2d816129ec565b61ffff809116602084015280608435612e45816129ec565b16604084015260a435612e57816129ec565b16606083015260c435612e6981610846565b166080820152612e83612e7a61085e565b151560a0830152565b612e97612e8e61086b565b151560c0830152565b60e0612ea1610679565b6001600160a01b0316910152565b63ffffffff9182168152610100810192916106879190602435612ed1816129ec565b61ffff809116602084015280604435612ee9816129ec565b166040840152606435612efb816129ec565b166060830152608435612f0d81610846565b166080820152612f1e612e7a610879565b612f29612e8e610886565b60e0612ea1610689565b9081602091031261000e575190565b506040513d6000823e3d90fd5b610687926001600160a01b03604051937fa9059cbb0000000000000000000000000000000000000000000000000000000060208601521660248401526044830152604482526080820182811067ffffffffffffffff821117612fb4575b604052613072565b612fbc61078a565b612fac565b601f19601f60209267ffffffffffffffff8111612fdf575b01160190565b612fe761078a565b612fd9565b9081602091031261000e57516114fe81610854565b1561300857565b608460405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6001600160a01b03169060405190613089826107de565b6020928383527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656484840152803b1561310057600082819282876130db9796519301915af16130d5613144565b90613185565b805190816130e857505050565b82610687936130fb938301019101612fec565b613001565b6064846040519062461bcd60e51b82526004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b3d1561316f573d9061315582612fc1565b916131636040519384610816565b82523d6000602084013e565b606090565b9060206114fe928181520190610b89565b90919015613191575090565b8151156131a15750805190602001fd5b61113e9060405191829162461bcd60e51b8352602060048401526024830190610b89565b906001600160a01b03806101a2541633036105285781511615613224576201518063ffffffff6131fc602084015163ffffffff1690565b161161320b57610687916156ce565b604051636a098dd160e11b815260116004820152602490fd5b604051636a098dd160e11b815260106004820152602490fd5b50634e487b7160e01b600052601160045260246000fd5b50634e487b7160e01b600052601260045260246000fd5b67ffffffffffffffff81160361000e57565b356114fe8161326b565b61344060e06106879261ffff813561329e816129ec565b1661ffff1960695416176069556132d760208201356132bc816129ec565b63ffff00001963ffff00006069549260101b16911617606955565b61330760408201356132e8816129ec565b65ffff000000001965ffff000000006069549260201b16911617606955565b6060810135613315816129ec565b7fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff67ffff0000000000006069549260301b1691161760695561339861335c60808301612a1c565b7fffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff69ffff00000000000000006069549260401b16911617606955565b6133e56133a760a08301612a1c565b7fffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffff6bffff000000000000000000006069549260501b16911617606955565b61343a6133f460c0830161327d565b7fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff73ffffffffffffffff0000000000000000000000006069549260601b16911617606955565b0161327d565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff00000000000000000000000000000000000000006069549260a01b16911617606955565b35906106878261326b565b909493926101409261357561356460e061016086019980356134ba816129ec565b61ffff809116885260208201356134d0816129ec565b1660208801526134f06134e560408301612e00565b61ffff166040890152565b61350a6134ff60608301612e00565b61ffff166060890152565b61352461351960808301612e00565b61ffff166080890152565b61353e61353360a08301612e00565b61ffff1660a0890152565b61355e61354d60c0830161348e565b67ffffffffffffffff1660c0890152565b0161348e565b67ffffffffffffffff1660e0850152565b6101008301526101208201520152565b1561358c57565b606460405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152fd5b811981116135dc570190565b6135e461323d565b0190565b60019060001981146135dc570190565b60d65492918315613709575b600090806136e757505080925b83811061362f5750821491821561362a5750600060d655565b60d655565b63ffffffff61363d82612d24565b90549060031b1c16600052606460205260409061366b6111de600284600020016001600160a01b0390541690565b803b1561000e5760006136c8935180927f512403360000000000000000000000000000000000000000000000000000000082528183816136b360048201906000602083019252565b03925af180156136da575b6136cd57506135e8565b613611565b80610d4b611261926107a1565b6136e2612f42565b6136be565b6136f190856135d0565b905081811015613702575b92613611565b50806136fc565b60009350613604565b60d754929183156137f4575b600090806137d257505080925b838110613749575082149182156137445750600060d755565b60d755565b63ffffffff61375782612d24565b90549060031b1c1660005260646020526040906001600160a01b03600283600020015416803b1561000e576000809160246137cd9551809481937f51240336000000000000000000000000000000000000000000000000000000008352600160048401525af180156136da576136cd57506135e8565b61372b565b6137dc90856135d0565b9050818110156137ed575b9261372b565b50806137e7565b6000935061371e565b1561380457565b606460405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152fd5b61385860ff610170541615613585565b60d2547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8111613910575b6001810160d255600081815260d36020526040902080546bffffffffffffffffffffffff163360601b6bffffffffffffffffffffffff19161781556bffffffffffffffffffffffff82166bffffffffffffffffffffffff198254161790556040518181527f7325fb14450d3e5eb288c620b4ff1d6b43a41b33b4a4f143ae88cd4c12f99ea360203392a290565b61391861323d565b613883565b359081600f0b820361000e57565b3590600382101561000e57565b809291610100918291031261000e5760405190810181811067ffffffffffffffff8211176139e8575b60405260e06139e381839561397581611534565b855261398360208201611534565b60208601526139946040820161391d565b60408601526139a560608201610696565b60608601526139b660808201612e00565b60808601526139c760a08201610893565b60a08601526139d860c0820161392b565b60c086015201610893565b910152565b6139f061078a565b613961565b906139ff8261230f565b613a0c6040519182610816565b828152601f19613a1c829461230f565b019060005b828110613a2d57505050565b806060602080938501015201613a21565b9190811015613a7f575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561000e570190565b613a87612d0d565b613a48565b50634e487b7160e01b600052602160045260246000fd5b60071115613aad57565b610687613a8c565b35600781101561000e5790565b919060208301926007821015613ad55752565b613add613a8c565b52565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e5760200191813603831361000e57565b919082604091031261000e5760208235613b4a81610846565b9201356114fe81610846565b602090805115613b64570190565b6135e4612d0d565b604090805160011015613b64570190565b6020918151811015613b92575b60051b010190565b613b9a612d0d565b613b8a565b9081606091031261000e578035613bb581610846565b9160406020830135613bc681611529565b9201356114fe81611529565b91906101208382031261000e576114fe9060208435613bf081610846565b9401613938565b809291039160c0831261000e5760a0601f198235613c1481610846565b94011261000e5760a060405191613c2a836107c2565b602081013583526040810135613c3f81610668565b60208401526060810135613c5281610854565b60408401526080810135613c6581610854565b60608401520135613c7581610854565b608082015290565b9081602091031261000e573590565b919082604091031261000e5760208235613ca581610846565b92013590565b60005b60088060ff83161015613d0d57811015613d12575b63ffffffff60018260031c8401015460e08360051b161c16908115613d0d57613ced600192613d7b565b60ff809116908114613d00575b01613cae565b613d0861323d565b613cfa565b505050565b613d1a612d0d565b613cc3565b6000821282600160ff1b018212811516613d6e575b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01821316613d62570390565b613d6a61323d565b0390565b613d7661323d565b613d34565b613d83613fe9565b613d9d8263ffffffff16600052606d602052604060002090565b805463ffffffff838116911614613d0d57613db7836144eb565b613dc8613dc38561410a565b614095565b93600160e01b80831090811591613f2c575b50613f255761068794613e76613e7b613ee194613e1b6003613e0f613ec79763ffffffff166000526064602052604060002090565b015460201c61ffff1690565b613e3b61ffff613e33613e2e8886613d1f565b6145f6565b921683613f37565b1015613ef657613e7660018801600160e01b7fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff825416179055565b61457a565b60018601907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000825416179055565b825463ffffffff1660209190911b63ffffffff1916178255565b9063ffffffff1663ffffffff19825416179055565b613e76600188017fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8154169055565b5050505050565b905085101538613dda565b9060001981830981830291828083109203918083039214613f9457612710908282111561000e577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b505061271091500490565b6000198282099082810292838084109303928084039314613fe05768010000000000000000918383111561000e570990828211900360c01b910360401c1790565b50505060401c90565b61a4b146148015614089575b801561407d575b156140735763ffffffff6040517fa3b1b31d00000000000000000000000000000000000000000000000000000000815260208160048160645afa908115614066575b60009161404a57501690565b614062915060203d81116109d9576109ca8183610816565b1690565b61406e612f42565b61403e565b63ffffffff431690565b5062066eec4614613ffc565b5062066eeb4614613ff5565b6001600160a01b03166401000276a3811080156140ec575b6140bb57806114fe91613f9f565b602490604051907f5d236c450000000000000000000000000000000000000000000000000000000082526004820152fd5b5073fffd8963efd1fc6a506488495d951d5263988d268110156140ad565b6141249063ffffffff166000526064602052604060002090565b600361414e6001600160a01b0392836001820154169063ffffffff938491015460301c16906148cf565b60020b9060008212156144e55781600003915b620d89e883116144bb5760018316156144925770ffffffffffffffffffffffffffffffffff6ffffcb933bd6fad37aa2d162d1a5940015b169260028116614476575b6004811661445a575b6008811661443e575b60108116614422575b60208116614406575b604081166143ea575b6080908181166143cf575b61010081166143b4575b6102008116614399575b610400811661437e575b6108008116614363575b6110008116614348575b612000811661432d575b6140008116614312575b61800081166142f7575b6201000081166142dc575b6202000081166142c2575b6204000081166142a8575b620800001661428d575b5060001261427d575b81166142745760ff60005b169060201c011690565b60ff600161426a565b906142879061460b565b9061425f565b6b048a170391f7dc42444e8fa26000929402901c9290614256565b6d2216e584f5fa1ea926041bedfe98909402811c9361424c565b936e5d6af8dedb81196699c329225ee60402811c93614241565b936f09aa508b5b7a84e1c677de54f3e99bc902811c93614236565b936f31be135f97d08fd981231505542fcfa602811c9361422b565b936f70d869a156d2a1b890bb3df62baf32f702811c93614221565b936fa9f746462d870fdf8a65dc1f90e061e502811c93614217565b936fd097f3bdfd2022b8845ad8f792aa582502811c9361420d565b936fe7159475a2c29b7443b29c7fa6e889d902811c93614203565b936ff3392b0822b70005940c7a398e4b70f302811c936141f9565b936ff987a7253ac413176f2b074cf7815e5402811c936141ef565b936ffcbe86c7900a88aedcffc83b479aa3a402811c936141e5565b936ffe5dee046a99a2a811c461f1969c305302811c936141db565b926fff2ea16466c96a3843ec78b326b528610260801c926141d0565b926fff973b41fa98c081472e6896dfb254c00260801c926141c7565b926fffcb9843d60f6159c9db58835c9266440260801c926141be565b926fffe5caca7e10e4e61c3624eaa0941cd00260801c926141b5565b926ffff2e50f5f656932ef12357cf3c7fdcc0260801c926141ac565b926ffff97272373d413259a46990580e213a0260801c926141a3565b70ffffffffffffffffffffffffffffffffff700100000000000000000000000000000000614198565b60046040517f2bc80f3a000000000000000000000000000000000000000000000000000000008152fd5b81614161565b63ffffffff80911660005260646020526020600360406000200154916024604051809481937fdd86c1010000000000000000000000000000000000000000000000000000000083528160301c16600483015260601c5afa90811561456d575b600091614555575090565b6114fe915060203d81116109d9576109ca8183610816565b614575612f42565b61454a565b600160e01b81116145a6577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b602490604051907f1ba344530000000000000000000000000000000000000000000000000000000082526004820152fd5b600160ff1b81146145e9575b60000390565b6145f161323d565b6145e3565b60008113156146025790565b6114fe906145d7565b8015614619575b6000190490565b614621613254565b614612565b60405190614633826107fa565b600282526040366020840137565b81601f8201121561000e578051916146588361230f565b926146666040519485610816565b808452602092838086019260051b82010192831161000e578301905b828210614690575050505090565b838091835161469e81610668565b815201910190614682565b91909160408184031261000e5780519267ffffffffffffffff9384811161000e5782019381601f8601121561000e578451946146e48661230f565b906146f26040519283610816565b868252602096878084019160051b8301019185831161000e578801905b82821061472e575050509483015190811161000e576114fe9201614641565b81518060060b810361000e57815290880190880161470f565b6020908160408183019282815285518094520193019160005b82811061476e575050505090565b835163ffffffff1685529381019392810192600101614760565b60060b9060060b906000821282667fffffffffffff190182128115166147be575b82667fffffffffffff01821316613d62570390565b6147c661323d565b6147a9565b60060b9060060b9081156147ff575b6000198214667fffffffffffff198214166147f3570590565b6147fb61323d565b0590565b614807613254565b6147da565b9060060b90811561481f575b60060b0790565b614827613254565b614818565b6000199060020b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000081146135dc570190565b908160e091031261000e57805161487481610668565b91602082015161488381611529565b916040810151614892816129ec565b9160608201516148a1816129ec565b9160808101516148b0816129ec565b9160a082015160ff8116810361000e5760c0909201516114fe81610854565b9063ffffffff81168015614a6e5761494e6001600160a01b03936149096148f4614626565b946148fe86613b56565b9063ffffffff169052565b60009485918261491887613b6c565b521693604051809381927f883bdbfd00000000000000000000000000000000000000000000000000000000835260048301614747565b0381865afa849181614a49575b506149ca57505060e060049160405192838092633850c7bd60e01b82525afa9182156149bd575b9161498b575090565b6149ac915060e03d81116149b6575b6149a48183610816565b81019061485e565b5050505050905090565b503d61499a565b6149c5612f42565b614982565b6149f59192506149ef6149e26149e96149e284613b6c565b5160060b90565b92613b56565b90614788565b9060060b614a0c614a0682846147cb565b60020b90565b928260060b129182614a2b575b5050614a225790565b6114fe9061482c565b614a40925090614a3a9161480c565b60060b90565b15153880614a19565b614a669192503d8087833e614a5e8183610816565b8101906146a9565b50903861495b565b50506114fe9060e06001600160a01b0391600460405180948193633850c7bd60e01b8352165afa908115614aa8575b60009161498b575090565b614ab0612f42565b614a9d565b919091614ac860ff610170541615613585565b6000821290614ad782856158e1565b93733fab135e76c5c0e85a60bf50f100c8cd912f7e5691823b1561000e5760405163f5a284a160e01b8152600481019190915263ffffffff919091166024820152604481018490526064808201526000608482018190529091829060a49082905af48015614b96575b614b83575b506000821315614b64575061168861068792546001600160a01b031690565b614b6c575050565b6116bf6116b961068793546001600160a01b031690565b80610d4b614b90926107a1565b38614b45565b614b9e612f42565b614b40565b909261068793604051937f23b872dd0000000000000000000000000000000000000000000000000000000060208601526001600160a01b03809216602486015216604484015260648301526064825260a0820182811067ffffffffffffffff821117612fb457604052613072565b614c2160ff610170541615613585565b8115611d3157733fab135e76c5c0e85a60bf50f100c8cd912f7e56803b1561000e576040517fd25c4a6f000000000000000000000000000000000000000000000000000000008152600481019290925260248201839052606460448301819052600090830181905290829060849082905af48015614ceb575b614cd8575b506000811315614cbf57610687906116886067546001600160a01b031690565b610687906116bf6116b96067546001600160a01b031690565b80610d4b614ce5926107a1565b38614c9f565b614cf3612f42565b614c9a565b90606091939293614d0f60ff610170541615613585565b614d188261598c565b828501516001600160a01b031680614dd1575b50614d6360405195869384937fc27789d100000000000000000000000000000000000000000000000000000000855260048501614eb9565b0381733fab135e76c5c0e85a60bf50f100c8cd912f7e565af48015614dc4575b60009081938291614d9e575b50606c54811061222a57509190565b915050614dba91925060603d811161228a576122798183610816565b9291909238614d8f565b614dcc612f42565b614d83565b614de4906122b1608088015161ffff1690565b38614d2b565b9081606091031261000e578051916040602083015192015190565b906003821015613ad55752565b614eaa60e061016093969563ffffffff610687966101808601998652166020850152805160020b6040850152602081015160020b60608501526040810151600f0b6080850152614e72606082015160a08601906001600160a01b03169052565b608081015161ffff1660c085015260a0810151151584830152614e9e60c0820151610100860190614e05565b01511515610120830152565b60646101408201520160019052565b614f1860e061016093969563ffffffff6000966101808601998652166020850152805160020b6040850152602081015160020b60608501526040810151600f0b6080850152614e72606082015160a08601906001600160a01b03169052565b60646101408201520152565b9082939291614f3960ff610170541615613585565b614f428261598c565b6040918291614fdb835195869384937f140cf61e00000000000000000000000000000000000000000000000000000000855260048501608061010092959463ffffffff6000956101208501988552166020840152805160408401526001600160a01b03602082015116606084015260408101511515828401526060810151151560a08401520151151560c0820152606460e08201520152565b0381733fab135e76c5c0e85a60bf50f100c8cd912f7e565af49384156150f1575b60009283956150cc575b50615010856145f6565b606c54811061192f57506001600160a01b0361503660208301516001600160a01b031690565b161515806150b6575b61504a575b50509190565b818101906150588251151590565b918261509a575b8215615073575b50501561189b5780615044565b5115915081615085575b503880615066565b90506150936118ef846145f6565b143861507d565b91506150a5866145f6565b6150af82516145f6565b149161505f565b506150c76118ce6060830151151590565b61503f565b909450816150e79293503d841161198f5761197d8183610816565b9190919338615006565b6150f9612f42565b614ffc565b919082604091031261000e576020825192015190565b608061010092959463ffffffff610687956101208501988552166020840152805160408401526001600160a01b03602082015116606084015260408101511515828401526060810151151560a08401520151151560c0820152606460e08201520160019052565b61518b60ff610170541615613585565b6151e560606151a48360005260d3602052604060002090565b604051809381927fdf19bf09000000000000000000000000000000000000000000000000000000008352600483016020606491939293604081019481520152565b0381733fab135e76c5c0e85a60bf50f100c8cd912f7e565af49182156152e7575b600092839284916152c1575b5061521d83856152f4565b92600085131561528f57907f688f0846fe2852572c467d5e769db101b0fea55e8849406d85c9fb322b95299b91615267866152606067546001600160a01b031690565b3390612f4f565b61527081615565565b604080519586526020860187905285015260608401523392608090a390565b6040517fef37dcc700000000000000000000000000000000000000000000000000000000815260048101869052602490fd5b919350506152dd915060603d811161228a576122798183610816565b9192909138615212565b6152ef612f42565b615206565b60008112817f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038313811516615337575b81600160ff1b038312166135dc570190565b61533f61323d565b615325565b6153c39161536e60409261535e60ff610170541615613585565b60005260d3602052604060002090565b6153778261598c565b825193849283927fec1464960000000000000000000000000000000000000000000000000000000084526004840160409063ffffffff6064939594606083019683521660208201520152565b0381733fab135e76c5c0e85a60bf50f100c8cd912f7e565af48015615468575b6000918291615448575b506000821315615416576114fe90615411836152606067546001600160a01b031690565b615565565b6040517fef37dcc700000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b9050615462915060403d811161198f5761197d8183610816565b386153ed565b615470612f42565b6153e3565b9290919261548960ff610170541615613585565b60005260d36020526040600020916154a08161598c565b606b5493733fab135e76c5c0e85a60bf50f100c8cd912f7e5693843b1561000e5763ffffffff9460009460c49360405197889687957fe0448f0a000000000000000000000000000000000000000000000000000000008752600487015216602485015260020b604484015260020b6064830152866084830152606460a48301525af48015615558575b615545575b506114fe816152606067546001600160a01b031690565b80610d4b615552926107a1565b3861552e565b615560612f42565b615529565b600081131561558a57610687906001600160a01b0380606754169060d5541690612f4f565b61559f6001600160a01b0360d55416916145d7565b813b1561000e576000916024839260405194859384927f379607f500000000000000000000000000000000000000000000000000000000845260048401525af180156155f6575b6155ed5750565b610687906107a1565b6155fe612f42565b6155e6565b61565a602060016001600160a01b03936156368587511682906001600160a01b03166001600160a01b0319825416179055565b019301519182511683906001600160a01b03166001600160a01b0319825416179055565b6020810151907fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff77ffffffff000000000000000000000000000000000000000078ff00000000000000000000000000000000000000000000000060408654940151151560c01b169360a01b16911617179055565b919063ffffffff83166001600160a01b03841615615864576157166118ce611a356157098463ffffffff166000526065602052604060002090565b546001600160a01b031690565b80615829575b6157c957926157807f52983c04d8ccd4808cd0fcb24e6e48106ecb41e803d6270c6c94a15e3ebd08d2939461577b615752610839565b6001600160a01b03851681529185602084015263ffffffff166000526065602052604060002090565b615603565b6157c460405192839283909291604060609160808401956001600160a01b038091168552815116602085015263ffffffff6020820151168285015201511515910152565b0390a1565b6157e7615709859263ffffffff166000526065602052604060002090565b6040517fa5d4d0b50000000000000000000000000000000000000000000000000000000081526001600160a01b03928316600482015291166024820152604490fd5b5061585f6118ce8561584e6157098563ffffffff166000526065602052604060002090565b6001600160a01b0390811691161490565b61571c565b6040517f76d8a93100000000000000000000000000000000000000000000000000000000815260006004820152602490fd5b60005260d3602052604060002090815460601c33036158b157565b60246040517f0504a20d000000000000000000000000000000000000000000000000000000008152336004820152fd5b63ffffffff90929192168060005260656020526040600020926001600160a01b038454161561595b571580615949575b6159185750565b602490604051907f9150f8c80000000000000000000000000000000000000000000000000000000082526004820152fd5b5060ff600184015460c01c1615615911565b602482604051907f6b9c1a9d0000000000000000000000000000000000000000000000000000000082526004820152fd5b63ffffffff1680600052606460205260406000206001600160a01b03815416156159f3576003015460501c60ff16156159c25750565b602490604051907fb0fdd2020000000000000000000000000000000000000000000000000000000082526004820152fd5b602482604051907fb842f5a70000000000000000000000000000000000000000000000000000000082526004820152fd5b6001600160a01b039182169116818110613d62570390565b6001600160a01b039182809216918291169204821181151516615a5d570290565b615a6561323d565b0290565b63ffffffff166000526064602052615aee6111de615add6001600160a01b039361ffff600460e0876001604060002001541660405192838092633850c7bd60e01b82525afa908115615b55575b600091615b31575b50828781168289161115615b2157615ad591615a24565b965b16615a3c565b6001600160a01b0361271091160490565b911611615af757565b60046040517f07a1db07000000000000000000000000000000000000000000000000000000008152fd5b90615b2b91615a24565b96615ad7565b615b49915060e03d81116149b6576149a48183610816565b50505050505038615abe565b615b5d612f42565b615ab6565b615b6a613fe9565b9063ffffffff91828216600052606d60205260406000209280845416911614600014615bb65750600101547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6114fe91506144eb565b615bc8613fe9565b9063ffffffff808216600052606d60205280604060002054931690831614600014615bf4575060201c90565b6114fe9150613dc39061410a565b805160051b810160209081018183015b818110615c1f5750505090565b80515481528201615c12565b9091615c4492811015615c48575b60051b810190613ae0565b9091565b615c50612d0d565b615c39565b908092918237016000815290565b60208183031261000e5780519067ffffffffffffffff821161000e570181601f8201121561000e578051615c9681612fc1565b92615ca46040519485610816565b8184526020828401011161000e576114fe9160208085019101610b5456fea2646970667358221220ce0c9dd12d7cf9ac7f88003d50982dae4b671420307d28b4df67edd28c55ad5464736f6c634300080e0033", + "deployedBytecode": "0x60806040526004361015610013575b600080fd5b60003560e01c806304a6f264146103335780630df181ea1461032a5780631340155114610321578063136439dd146103185780631e2eaeaf1461030f5780632a90b8da146103065780633562490c146102fd57806335876476146102f45780633d0aea3d146102eb5780633d48e983146102e25780633d56a35e146102d95780633ffe794c146102d057806340c4f69b146102c7578063424cd833146102be57806343afafba146102b5578063569634d3146102ac5780635aa6e675146102a35780635c975abb1461029a5780636a486482146102915780636ae7323014610288578063706bdd251461027f5780637cc2f4f5146102765780637d2efe071461026d57806383d778eb146102645780638ce25a931461025b5780638f24ab11146102525780638f8022bc146102495780639cd1be58146102405780639dca362f14610237578063a05c8baf1461022e578063ac9650d814610225578063b79023031461021c578063c7505c1514610213578063ce4c18de1461020a578063dbc0c08514610201578063dbd035ff146101f8578063e3d41c18146101ef578063e450f6f4146101e6578063e67ed1df146101dd5763fabc1cbc146101d557600080fd5b61000e6126ca565b5061000e6125f1565b5061000e61249c565b5061000e612408565b5061000e612371565b5061000e6122e6565b5061000e6122be565b5061000e612124565b5061000e6120fc565b5061000e61201b565b5061000e611d9b565b5061000e611d5b565b5061000e611c24565b5061000e611bab565b5061000e6119c2565b5061000e6119a3565b5061000e611757565b5061000e611598565b5061000e61153f565b5061000e611501565b5061000e61145a565b5061000e611381565b5061000e61135c565b5061000e611333565b5061000e611305565b5061000e6112bd565b5061000e611142565b5061000e610c2e565b5061000e610a24565b5061000e6109fc565b5061000e61092c565b5061000e61089e565b5061000e6106a1565b5061000e6105f5565b5061000e610582565b5061000e610562565b5061000e61045e565b5061000e610435565b5061000e610370565b5061000e610347565b600091031261000e57565b503461000e57600060031936011261000e5760206001600160a01b036101a55416604051908152f35b503461000e57600060206003193601126104325761039460ff610170541615613585565b61039f600435615896565b6103a881613cab565b8173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__91823b1561042e576044604051809481937feaf393260000000000000000000000000000000000000000000000000000000083526004830152606460248301525af48015610421575b610412575b50604051f35b61041b906107a1565b3861040c565b610429612f42565b610407565b5080fd5b80fd5b503461000e57600060031936011261000e5760206001600160a01b036101a45416604051908152f35b503461000e57602060031936011261000e576001600160a01b03806101a354163314159081610552575b506105285761017061049e60ff82541615613585565b60d7546104fe576104b36004356066546135f8565b6104ba575b005b600160ff1982546104ce60ff821615613585565b161790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b60046040517fd2067f43000000000000000000000000000000000000000000000000000000008152fd5b60046040517fd7a2ae6a000000000000000000000000000000000000000000000000000000008152fd5b6101a25416331415905038610488565b503461000e57602060031936011261000e57602060043554604051908152f35b503461000e57600060031936011261000e576101a48054906001600160a01b0390818316803303610528576000936101a2805492806040519685167f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808989a36001600160a01b0319809416179055169055f35b503461000e57600060031936011261000e576101a58054906001600160a01b0390818316803303610528576000936101a3805492806040519685167f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb28989a36001600160a01b0319809416179055169055f35b6001600160a01b0381160361000e57565b610124359061068782610668565b565b60e4359061068782610668565b359061068782610668565b503461000e5760e060031936011261000e576004356106bf81610668565b6107396024356106ce81610668565b6044356106da81610668565b6064356106e681610668565b608435906106f382610668565b60a4359261070084610668565b60c4359461070d86610668565b61013d5460ff8160081c16908160001461077d575061072d303b1561279e565b1597886107505761280f565b61073f57005b6104b861013d61ff00198154169055565b61076561013d61010061ff0019825416179055565b61077861013d600160ff19825416179055565b61280f565b60ff61072d91161561279e565b50634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116107b557604052565b6107bd61078a565b604052565b60a0810190811067ffffffffffffffff8211176107b557604052565b6040810190811067ffffffffffffffff8211176107b557604052565b6060810190811067ffffffffffffffff8211176107b557604052565b90601f601f19910116810190811067ffffffffffffffff8211176107b557604052565b60405190610687826107de565b63ffffffff81160361000e57565b8015150361000e57565b60e4359061068782610854565b610104359061068782610854565b60a4359061068782610854565b60c4359061068782610854565b359061068782610854565b503461000e57608060031936011261000e576004356108bc81610668565b606060231936011261000e576040516104b8916060820167ffffffffffffffff81118382101761091f575b6040526024356108f681610668565b825260443561090481610846565b602083015260643561091581610854565b60408301526131c5565b61092761078a565b6108e7565b503461000e57600060031936011261000e576001600160a01b03806101a3541633811415806109ed575b610528576067546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526104b89390929116602083602481845afa9283156109e0575b6000936109b0575b50612f4f565b6109d291935060203d81116109d9575b6109ca8183610816565b810190612f33565b91386109aa565b503d6109c0565b6109e8612f42565b6109a2565b5033826101a254161415610956565b503461000e57600060031936011261000e5760206001600160a01b0360d45416604051908152f35b503461000e5761014060031936011261000e576001600160a01b038060d454163303610af957610a7d63ffffffff600435610a5e81610668565b1691826000526064602052604060002054166001600160a01b03161590565b15610ae357610ade81610ac9610ac47f4182acc9c169391ef7e765eb446fc15c9d49bc73060c678bf4c424a5c0dbdbcb9463ffffffff166000526064602052604060002090565b612bdc565b610ad281612d72565b60405191829182612e0b565b0390a1005b634e487b7160e01b600052600160045260246000fd5b60046040517f85734f31000000000000000000000000000000000000000000000000000000008152fd5b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b918091926000905b828210610b74575011610b6d575050565b6000910152565b91508060209183015181860152018291610b5c565b90601f19601f602093610ba781518092818752878088019101610b54565b0116010190565b602080820190808352835180925260408301928160408460051b8301019501936000915b848310610be25750505050505090565b9091929394958480610c1e837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a51610b89565b9801930193019194939290610bd2565b503461000e5760408060031936011261000e57600480359160243567ffffffffffffffff811161000e57610c659036908401610b23565b610c71819492946139f5565b93610c868660005260d3602052604060002090565b95610c9087613cab565b60008781938295835b818110610e0b5750505050610dfb575b50610d64575b610cc5575b815180610cc18582610bae565b0390f35b73__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__90813b1561000e5782517f998c53350000000000000000000000000000000000000000000000000000000081529081019485526001602086015260646040860152610cc19490916000918391908290819060600103915af48015610d57575b15610cb45780610d4b610d51926107a1565b8061033c565b38610cb4565b610d5f612f42565b610d39565b73__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__803b1561000e576000845180927f651524ed0000000000000000000000000000000000000000000000000000000082528180610dc58b8983016020606491939293604081019481520152565b03915af48015610dee575b610ddb575b50610caf565b80610d4b610de8926107a1565b38610dd5565b610df6612f42565b610dd0565b610e0490615896565b5038610ca9565b9091929693610e23610e1e838587613a3e565b613ab5565b610e2c81613aa3565b610e84575080610e6c610e5b610e53610e49610e71958789613a3e565b6020810190613ae0565b810190613c8c565b906001978015610e7a575b9a614ab5565b6135e8565b908a9291610c99565b5060008212610e66565b939650610e95610e1e828486613a3e565b93610e9f85613aa3565b6001948503610eee5750610ec2610eba610e49838587613a3e565b810190613c7d565b93610ecd858d614c11565b6000819512610ee1575b50610e71906135e8565b9650869550610e71610ed7565b6002610f01610e1e8486889c969c613a3e565b610f0a81613aa3565b03610f8b575050610f5d610f6b610f22888486613a3e565b610f468d610f40610f3860209485810190613ae0565b810190613bf7565b91614f24565b8c5192830191825260208201529092839160400190565b03601f198101835282610816565b610f75878b613b7d565b52610f80868a613b7d565b50610e7183966135e8565b6003610f9b610e1e8a8688613a3e565b610fa481613aa3565b03610fe0575050610f5d610f6b610fbc888486613a3e565b610f468d610fda610fd260209485810190613ae0565b810190613bd2565b91614cf8565b93509587610ff2610e1e838587613a3e565b610ffb81613aa3565b0361102d5780611027611020611018610e49610e71958789613a3e565b810190613b9f565b9189615475565b506135e8565b600561103d610e1e838587613a3e565b61104681613aa3565b0361107c578061102761107761106e611066610e49610e7196888a613a3e565b8101906114e9565b63ffffffff1690565b61517b565b600661108c610e1e838587613a3e565b61109581613aa3565b036110fc57806110a9610e71928486613a3e565b6110e76110d563ffffffff6110ce6110c660209586810190613ae0565b810190613b31565b9116615344565b8c519283019081528290602001610f5d565b6110f1828d613b7d565b52611027818c613b7d565b61110f610e1e61113e928a948c96613a3e565b92519283927f62c9ca420000000000000000000000000000000000000000000000000000000084528301613ac2565b0390fd5b503461000e5760208060031936011261000e5760665460d854600492833582156112b4575b600090806112915750508293915b84811061119257505050810361118d5750600060d855005b60d855005b806000836111ea6111de60026111d063ffffffff6111b261123399612d24565b90549060031b1c1663ffffffff166000526064602052604060002090565b01546001600160a01b031690565b6001600160a01b031690565b86604051809481937f5e622abc0000000000000000000000000000000000000000000000000000000083525af1908115611284575b600091611267575b508061123857506135e8565b611175565b6112619061124e6067546001600160a01b031690565b6001600160a01b036101a3541690612f4f565b38611027565b61127e9150843d86116109d9576109ca8183610816565b38611227565b61128c612f42565b61121f565b61129b90846135d0565b9050838110156112ad575b9391611175565b50826112a6565b60009250611167565b503461000e57604060031936011261000e5760206112fd6024356004356112e382610846565b8060005260d384526112f86040600020613cab565b615344565b604051908152f35b503461000e57602060031936011261000e576104b86004358060005260d36020526110776040600020613cab565b503461000e57600060031936011261000e5760206001600160a01b036101a25416604051908152f35b503461000e57600060031936011261000e57602060ff61017054166040519015158152f35b503461000e57604060031936011261000e57610cc16024356113a281610846565b60043560005260d360205263ffffffff604060002091604051927f7188a1ed00000000000000000000000000000000000000000000000000000000845260048401521660248201526064604482015260208160648173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af490811561144d575b60009161142f575b506040519081529081906020820190565b611447915060203d81116109d9576109ca8183610816565b3861141e565b611455612f42565b611416565b503461000e57602060031936011261000e5760043561147881610668565b6001600160a01b03806101a35416331415806114da575b610528576000916101a5906001600160a01b0319838354921691826040519582167f9b068aae3039a2512c2f13bffb5fd9d95b1895b276b5c7ddf1d4fa24ec3686588888a316179055f35b5033816101a25416141561148f565b9081602091031261000e57356114fe81610846565b90565b503461000e57602060031936011261000e5760206112fd60043561152481610846565b615b62565b8060020b0361000e57565b359061068782611529565b503461000e57608060031936011261000e576104b860043560243561156381610846565b6044359061157082611529565b6064359261157d84611529565b8060005260d36020526115936040600020613cab565b615475565b503461000e57606060031936011261000e576024356115b681610846565b604435610170906115cb60ff83541615613585565b6115d6600435615896565b916115e083613cab565b6000936115f460ff86851293541615613585565b846115ff83836158e1565b9473__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__803b156116ee5760405163f5a284a160e01b8152600481019290925263ffffffff93909316602482015260448101859052606480820152831515608482015291829060a49082905af480156116e1575b6116ce575b5083821315611696575061168861169192546001600160a01b031690565b30903390614ba3565b604051f35b6116a2575b5050604051f35b6116bf6116b96116c793546001600160a01b031690565b916145d7565b903390612f4f565b388061169b565b80610d4b6116db926107a1565b3861166a565b6116e9612f42565b611665565b8280fd5b60431960a091011261000e576040519061170b826107c2565b81604435815260643561171d81610668565b602082015260843561172e81610854565b604082015260a43561173f81610854565b6060820152608060c4359161175383610854565b0152565b503461000e5760e060031936011261000e5760243561177581610846565b61177e366116f2565b809161017061179160ff82541615613585565b6117b360ff6117a1600435615896565b926117ab84613cab565b541615613585565b6117bc8261598c565b60409182916117f7835195869384937f140cf61e00000000000000000000000000000000000000000000000000000000855260048501615114565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af4928315611996575b6000928394611961575b5061182c846145f6565b606c54811061192f57506001600160a01b0361185260208301516001600160a01b031690565b16151580611919575b611872575b50519081526020810191909152604090f35b818101906118808251151590565b91826118fd575b82156118c4575b50501561189b5738611860565b600490517f07a1db07000000000000000000000000000000000000000000000000000000008152fd5b51909150156118d2565b1590565b90816118e1575b50388061188e565b90506118f66118ef846145f6565b91516145f6565b14386118d9565b9150611908856145f6565b61191282516145f6565b1491611887565b5061192a6118ce6060830151151590565b61185b565b82517f256d6b9a0000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b909350816119859293503d841161198f575b61197d8183610816565b8101906150fe565b9190919238611822565b503d611973565b61199e612f42565b611818565b503461000e57600060031936011261000e57602060d254604051908152f35b503461000e5761010060031936011261000e5760048035906119e382610846565b60e060231936011261000e576001600160a01b036101a254163303611b8357611a276003611a218463ffffffff166000526064602052604060002090565b01612a64565b611a42611a356111de612a4b565b6001600160a01b03161590565b611b655763ffffffff61012c81611a57612a26565b1610908115611b4f575b50611b305761ffff6127108082611a766129f8565b1611611b1257611a8e611a87612a04565b61ffff1690565b11611af4576107d090611a9f612a10565b1611611ad5576040517f4182acc9c169391ef7e765eb446fc15c9d49bc73060c678bf4c424a5c0dbdbcb9080610ade8582612eaf565b604051636a098dd160e11b815260249181019182529081906020010390fd5b604051636a098dd160e11b8152602381840190815281906020010390fd5b604051636a098dd160e11b8152602281850190815281906020010390fd5b604051636a098dd160e11b815260219181019182529081906020010390fd5b620151809150611b5d612a26565b161138611a61565b604051636a098dd160e11b8152602091810182815290918291010390fd5b6040517fd7a2ae6a000000000000000000000000000000000000000000000000000000008152fd5b503461000e57602060031936011261000e57600435611bc981610668565b6001600160a01b03806101a254163303610528576000916101a4906001600160a01b0319838354921691826040519582167f8c405decc72a19ef328c92989ce6db4e4a498e1c246413fd60997a3051ba5cff8888a316179055f35b503461000e57604060031936011261000e57602435610170611c4a60ff82541615613585565b611c5a60ff6117a1600435615896565b8115611d315773__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__803b1561000e576040517fd25c4a6f000000000000000000000000000000000000000000000000000000008152600481019290925260248201839052606460448301819052600190830152600090829060849082905af48015611d24575b611d11575b506000811315611cf8576104b8906116886067546001600160a01b031690565b6104b8906116bf6116b96067546001600160a01b031690565b80610d4b611d1e926107a1565b38611cd8565b611d2c612f42565b611cd3565b60046040517f1f2a2005000000000000000000000000000000000000000000000000000000008152fd5b503461000e57600060031936011261000e5760206112fd613848565b60031961010091011261000e57600490565b60431961010091011261000e57604490565b503461000e5761016060031936011261000e57611db736611d77565b610104356101243591610144356001600160a01b036101a254163303610528576127109361ffff8581611de986612a1c565b16116120025785611dff611a8760208701612a1c565b11611fe95760409580611e16611a87898801612a1c565b11611fd15780611e2b611a8760608801612a1c565b11611fb957611e3f611a8760808701612a1c565b11611fa1576103e890611e5460a08601612a1c565b1611611f8957633b9aca008067ffffffffffffffff611e7560c0870161327d565b1611611f715780611e98611e8b60e0870161327d565b67ffffffffffffffff1690565b11611f5957808511611f4157808211611f29578211611f115791611f0b60009594927f697aec6e94e319190380ab0f1f10018d81b64da2479eb874be92c9a733e0a83794611ee584613287565b611eee85606b55565b611ef781606c55565b611f0082606a55565b865194859485613499565b0390a151f35b8451636a098dd160e11b8152603a6004820152602490fd5b8551636a098dd160e11b815260396004820152602490fd5b8551636a098dd160e11b815260386004820152602490fd5b8551636a098dd160e11b815260376004820152602490fd5b8551636a098dd160e11b815260366004820152602490fd5b8451636a098dd160e11b815260356004820152602490fd5b8551636a098dd160e11b815260346004820152602490fd5b8651636a098dd160e11b815260336004820152602490fd5b8651636a098dd160e11b815260326004820152602490fd5b604051636a098dd160e11b815260316004820152602490fd5b604051636a098dd160e11b815260306004820152602490fd5b50602060031936011261000e576004803567ffffffffffffffff811161000e576120489036908301610b23565b90612052826139f5565b9160005b81811061206b5760405180610cc18682610bae565b600080612079838587615c2b565b6040939161208b855180938193615c55565b0390305af490612099613144565b918290156120c2575050906120bd916120b28287613b7d565b526110278186613b7d565b612056565b826044899394511061000e5761113e91836120e7920160248091518301019101615c63565b925192839262461bcd60e51b84528301613174565b503461000e57600060031936011261000e5760206001600160a01b0360d55416604051908152f35b503461000e5761014060031936011261000e5760243561214381610846565b606061214e36611d89565b916101709261216160ff85541615613585565b61218e60ff612185612174600435615896565b9361217e85613cab565b3690613938565b95541615613585565b6121978261598c565b828401516001600160a01b03168061229e575b506121e260405194859384937fc27789d100000000000000000000000000000000000000000000000000000000855260048501614e12565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af48015612291575b6000908192829161225d575b50606c54811061222a5750604080519182526020820192909252f35b6040517f256d6b9a0000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b915050612281915060603d811161228a575b6122798183610816565b810190614dea565b9190913861220e565b503d61226f565b612299612f42565b612202565b6122b8906122b1608087015161ffff1690565b9084615a69565b386121aa565b503461000e57602060031936011261000e5760206112fd6004356122e181610846565b615bc0565b503461000e57600060031936011261000e5760206001600160a01b036101a35416604051908152f35b60209067ffffffffffffffff8111612329575b60051b0190565b61233161078a565b612322565b6020908160408183019282815285518094520193019160005b82811061235d575050505090565b83518552938101939281019260010161234f565b503461000e5760208060031936011261000e5760043567ffffffffffffffff811161000e573660238201121561000e578060040135906123b08261230f565b916123be6040519384610816565b80835260248484019160051b8301019136831161000e57602401905b8282106123f957610cc16123ed85615c02565b60405191829182612336565b813581529084019084016123da565b503461000e57602060031936011261000e5760043560005260d3602052610cc16040600020604051907fc4b22b8600000000000000000000000000000000000000000000000000000000825260048201526064602482015260208160448173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af490811561144d5760009161142f57506040519081529081906020820190565b503461000e57604060031936011261000e576004356124ba81610846565b602435906124c6613848565b90610170926124d960ff85541615613585565b6124e283615896565b936124ec85613cab565b6124fe60ff6000841292541615613585565b61250881846158e1565b9273__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__90813b1561000e5760405163f5a284a160e01b8152600481019790975263ffffffff166024870152604486018390526064808701528115156084870152610cc19590600090829060a49082905af480156125e4575b6125d1575b5060008213156125a7575061168861259792546001600160a01b031690565b6040519081529081906020820190565b6125b3575b5050612597565b6116bf6116b96125ca93546001600160a01b031690565b38806125ac565b80610d4b6125de926107a1565b38612578565b6125ec612f42565b612573565b503461000e5760408060031936011261000e5760243561261081610854565b60043560005260d360205281600020908251917f0c6d7f3400000000000000000000000000000000000000000000000000000000835260048301521515602482015260646044820152818160648173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af49182156126bd575b60009182936126985750519081526020810191909152604090f35b816126b5929450610cc193503d851161198f5761197d8183610816565b929091611860565b6126c5612f42565b61267d565b503461000e57602060031936011261000e576001600160a01b03806101a35416331415908161278e575b506105285761017061270960ff8254166137fd565b60d6546127645761271e600435606654613712565b61272457005b60ff19815461273560ff82166137fd565b1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b60046040517ffc23b9cd000000000000000000000000000000000000000000000000000000008152fd5b6101a254163314159050386126f4565b156127a557565b608460405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b93916128a17f39355f2f5c8206286978f443aa8126bbd29fa09c53c04569502647f3a59c8cb2936000958694986001600160a01b039a8b8092816001600160a01b03199c168c60d454161760d4558185168c6067541617606755168a60d554161760d55516886068541617606855896040519261288b846107fa565b168252603c6020830152600160408301526156ce565b61013d9680885460ff8160081c169081861461295957506128c3303b1561279e565b15978861292c575b16916101a2838882541617905560405192847f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808186a31694856101a391825416179055a361291d575b50610687612966565b61ff0019815416905538612914565b61294161013d61010061ff0019825416179055565b61295461013d600160ff19825416179055565b6128cb565b60ff6128c391161561279e565b60ff61013d5460081c16156129825761017060ff198154169055565b608460405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152fd5b61ffff81160361000e57565b6024356114fe816129ec565b6044356114fe816129ec565b6064356114fe816129ec565b356114fe816129ec565b6084356114fe81610846565b60e4356114fe81610854565b610104356114fe81610854565b60e4356114fe81610668565b610124356114fe81610668565b61068790612a89602435612a77816129ec565b829061ffff1661ffff19825416179055565b612ab2604435612a98816129ec565b825463ffff0000191660109190911b63ffff000016178255565b612adf606435612ac1816129ec565b825465ffff00000000191660209190911b65ffff0000000016178255565b608435612aeb81610846565b69ffffffff0000000000001969ffffffff00000000000083549260301b169116178155612b5960a435612b1d81610854565b82547fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff1690151560501b6aff0000000000000000000016178255565b612ba560c435612b6881610854565b82547fffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffff1690151560581b6bff000000000000000000000016178255565b60e43590612bb282610668565b906bffffffffffffffffffffffff6bffffffffffffffffffffffff1983549260601b169116179055565b600361068791612c0d600435612bf181610668565b82906001600160a01b03166001600160a01b0319825416179055565b612c3b602435612c1c81610668565b60018301906001600160a01b03166001600160a01b0319825416179055565b612c69604435612c4a81610668565b60028301906001600160a01b03166001600160a01b0319825416179055565b01612c79606435612a77816129ec565b612c88608435612a98816129ec565b612c9760a435612ac1816129ec565b60c435612ca381610846565b69ffffffff0000000000001969ffffffff00000000000083549260301b169116178155612cd1612b1d612a32565b612cdc612b68612a3e565b612ce4612a57565b6bffffffffffffffffffffffff6bffffffffffffffffffffffff1983549260601b169116179055565b50634e487b7160e01b600052603260045260246000fd5b90606654821015612d65575b6066600052601c8260031c7f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354019260021b1690565b612d6d612d0d565b612d30565b6066549068010000000000000000821015612df3575b6001820180606655821015612de6575b60666000528160031c7f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354019160e083549160051b169163ffffffff9283811b93849216901b16911916179055565b612dee612d0d565b612d98565b612dfb61078a565b612d88565b3590610687826129ec565b63ffffffff9182168152610100810192916106879190606435612e2d816129ec565b61ffff809116602084015280608435612e45816129ec565b16604084015260a435612e57816129ec565b16606083015260c435612e6981610846565b166080820152612e83612e7a61085e565b151560a0830152565b612e97612e8e61086b565b151560c0830152565b60e0612ea1610679565b6001600160a01b0316910152565b63ffffffff9182168152610100810192916106879190602435612ed1816129ec565b61ffff809116602084015280604435612ee9816129ec565b166040840152606435612efb816129ec565b166060830152608435612f0d81610846565b166080820152612f1e612e7a610879565b612f29612e8e610886565b60e0612ea1610689565b9081602091031261000e575190565b506040513d6000823e3d90fd5b610687926001600160a01b03604051937fa9059cbb0000000000000000000000000000000000000000000000000000000060208601521660248401526044830152604482526080820182811067ffffffffffffffff821117612fb4575b604052613072565b612fbc61078a565b612fac565b601f19601f60209267ffffffffffffffff8111612fdf575b01160190565b612fe761078a565b612fd9565b9081602091031261000e57516114fe81610854565b1561300857565b608460405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6001600160a01b03169060405190613089826107de565b6020928383527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656484840152803b1561310057600082819282876130db9796519301915af16130d5613144565b90613185565b805190816130e857505050565b82610687936130fb938301019101612fec565b613001565b6064846040519062461bcd60e51b82526004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b3d1561316f573d9061315582612fc1565b916131636040519384610816565b82523d6000602084013e565b606090565b9060206114fe928181520190610b89565b90919015613191575090565b8151156131a15750805190602001fd5b61113e9060405191829162461bcd60e51b8352602060048401526024830190610b89565b906001600160a01b03806101a2541633036105285781511615613224576201518063ffffffff6131fc602084015163ffffffff1690565b161161320b57610687916156ce565b604051636a098dd160e11b815260116004820152602490fd5b604051636a098dd160e11b815260106004820152602490fd5b50634e487b7160e01b600052601160045260246000fd5b50634e487b7160e01b600052601260045260246000fd5b67ffffffffffffffff81160361000e57565b356114fe8161326b565b61344060e06106879261ffff813561329e816129ec565b1661ffff1960695416176069556132d760208201356132bc816129ec565b63ffff00001963ffff00006069549260101b16911617606955565b61330760408201356132e8816129ec565b65ffff000000001965ffff000000006069549260201b16911617606955565b6060810135613315816129ec565b7fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff67ffff0000000000006069549260301b1691161760695561339861335c60808301612a1c565b7fffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff69ffff00000000000000006069549260401b16911617606955565b6133e56133a760a08301612a1c565b7fffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffff6bffff000000000000000000006069549260501b16911617606955565b61343a6133f460c0830161327d565b7fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff73ffffffffffffffff0000000000000000000000006069549260601b16911617606955565b0161327d565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff00000000000000000000000000000000000000006069549260a01b16911617606955565b35906106878261326b565b909493926101409261357561356460e061016086019980356134ba816129ec565b61ffff809116885260208201356134d0816129ec565b1660208801526134f06134e560408301612e00565b61ffff166040890152565b61350a6134ff60608301612e00565b61ffff166060890152565b61352461351960808301612e00565b61ffff166080890152565b61353e61353360a08301612e00565b61ffff1660a0890152565b61355e61354d60c0830161348e565b67ffffffffffffffff1660c0890152565b0161348e565b67ffffffffffffffff1660e0850152565b6101008301526101208201520152565b1561358c57565b606460405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152fd5b811981116135dc570190565b6135e461323d565b0190565b60019060001981146135dc570190565b60d65492918315613709575b600090806136e757505080925b83811061362f5750821491821561362a5750600060d655565b60d655565b63ffffffff61363d82612d24565b90549060031b1c16600052606460205260409061366b6111de600284600020016001600160a01b0390541690565b803b1561000e5760006136c8935180927f512403360000000000000000000000000000000000000000000000000000000082528183816136b360048201906000602083019252565b03925af180156136da575b6136cd57506135e8565b613611565b80610d4b611261926107a1565b6136e2612f42565b6136be565b6136f190856135d0565b905081811015613702575b92613611565b50806136fc565b60009350613604565b60d754929183156137f4575b600090806137d257505080925b838110613749575082149182156137445750600060d755565b60d755565b63ffffffff61375782612d24565b90549060031b1c1660005260646020526040906001600160a01b03600283600020015416803b1561000e576000809160246137cd9551809481937f51240336000000000000000000000000000000000000000000000000000000008352600160048401525af180156136da576136cd57506135e8565b61372b565b6137dc90856135d0565b9050818110156137ed575b9261372b565b50806137e7565b6000935061371e565b1561380457565b606460405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152fd5b61385860ff610170541615613585565b60d2547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8111613910575b6001810160d255600081815260d36020526040902080546bffffffffffffffffffffffff163360601b6bffffffffffffffffffffffff19161781556bffffffffffffffffffffffff82166bffffffffffffffffffffffff198254161790556040518181527f7325fb14450d3e5eb288c620b4ff1d6b43a41b33b4a4f143ae88cd4c12f99ea360203392a290565b61391861323d565b613883565b359081600f0b820361000e57565b3590600382101561000e57565b809291610100918291031261000e5760405190810181811067ffffffffffffffff8211176139e8575b60405260e06139e381839561397581611534565b855261398360208201611534565b60208601526139946040820161391d565b60408601526139a560608201610696565b60608601526139b660808201612e00565b60808601526139c760a08201610893565b60a08601526139d860c0820161392b565b60c086015201610893565b910152565b6139f061078a565b613961565b906139ff8261230f565b613a0c6040519182610816565b828152601f19613a1c829461230f565b019060005b828110613a2d57505050565b806060602080938501015201613a21565b9190811015613a7f575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561000e570190565b613a87612d0d565b613a48565b50634e487b7160e01b600052602160045260246000fd5b60071115613aad57565b610687613a8c565b35600781101561000e5790565b919060208301926007821015613ad55752565b613add613a8c565b52565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561000e570180359067ffffffffffffffff821161000e5760200191813603831361000e57565b919082604091031261000e5760208235613b4a81610846565b9201356114fe81610846565b602090805115613b64570190565b6135e4612d0d565b604090805160011015613b64570190565b6020918151811015613b92575b60051b010190565b613b9a612d0d565b613b8a565b9081606091031261000e578035613bb581610846565b9160406020830135613bc681611529565b9201356114fe81611529565b91906101208382031261000e576114fe9060208435613bf081610846565b9401613938565b809291039160c0831261000e5760a0601f198235613c1481610846565b94011261000e5760a060405191613c2a836107c2565b602081013583526040810135613c3f81610668565b60208401526060810135613c5281610854565b60408401526080810135613c6581610854565b60608401520135613c7581610854565b608082015290565b9081602091031261000e573590565b919082604091031261000e5760208235613ca581610846565b92013590565b60005b60088060ff83161015613d0d57811015613d12575b63ffffffff60018260031c8401015460e08360051b161c16908115613d0d57613ced600192613d7b565b60ff809116908114613d00575b01613cae565b613d0861323d565b613cfa565b505050565b613d1a612d0d565b613cc3565b6000821282600160ff1b018212811516613d6e575b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01821316613d62570390565b613d6a61323d565b0390565b613d7661323d565b613d34565b613d83613fe9565b613d9d8263ffffffff16600052606d602052604060002090565b805463ffffffff838116911614613d0d57613db7836144eb565b613dc8613dc38561410a565b614095565b93600160e01b80831090811591613f2c575b50613f255761068794613e76613e7b613ee194613e1b6003613e0f613ec79763ffffffff166000526064602052604060002090565b015460201c61ffff1690565b613e3b61ffff613e33613e2e8886613d1f565b6145f6565b921683613f37565b1015613ef657613e7660018801600160e01b7fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff825416179055565b61457a565b60018601907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000825416179055565b825463ffffffff1660209190911b63ffffffff1916178255565b9063ffffffff1663ffffffff19825416179055565b613e76600188017fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8154169055565b5050505050565b905085101538613dda565b9060001981830981830291828083109203918083039214613f9457612710908282111561000e577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b505061271091500490565b6000198282099082810292838084109303928084039314613fe05768010000000000000000918383111561000e570990828211900360c01b910360401c1790565b50505060401c90565b61a4b146148015614089575b801561407d575b156140735763ffffffff6040517fa3b1b31d00000000000000000000000000000000000000000000000000000000815260208160048160645afa908115614066575b60009161404a57501690565b614062915060203d81116109d9576109ca8183610816565b1690565b61406e612f42565b61403e565b63ffffffff431690565b5062066eec4614613ffc565b5062066eeb4614613ff5565b6001600160a01b03166401000276a3811080156140ec575b6140bb57806114fe91613f9f565b602490604051907f5d236c450000000000000000000000000000000000000000000000000000000082526004820152fd5b5073fffd8963efd1fc6a506488495d951d5263988d268110156140ad565b6141249063ffffffff166000526064602052604060002090565b600361414e6001600160a01b0392836001820154169063ffffffff938491015460301c16906148cf565b60020b9060008212156144e55781600003915b620d89e883116144bb5760018316156144925770ffffffffffffffffffffffffffffffffff6ffffcb933bd6fad37aa2d162d1a5940015b169260028116614476575b6004811661445a575b6008811661443e575b60108116614422575b60208116614406575b604081166143ea575b6080908181166143cf575b61010081166143b4575b6102008116614399575b610400811661437e575b6108008116614363575b6110008116614348575b612000811661432d575b6140008116614312575b61800081166142f7575b6201000081166142dc575b6202000081166142c2575b6204000081166142a8575b620800001661428d575b5060001261427d575b81166142745760ff60005b169060201c011690565b60ff600161426a565b906142879061460b565b9061425f565b6b048a170391f7dc42444e8fa26000929402901c9290614256565b6d2216e584f5fa1ea926041bedfe98909402811c9361424c565b936e5d6af8dedb81196699c329225ee60402811c93614241565b936f09aa508b5b7a84e1c677de54f3e99bc902811c93614236565b936f31be135f97d08fd981231505542fcfa602811c9361422b565b936f70d869a156d2a1b890bb3df62baf32f702811c93614221565b936fa9f746462d870fdf8a65dc1f90e061e502811c93614217565b936fd097f3bdfd2022b8845ad8f792aa582502811c9361420d565b936fe7159475a2c29b7443b29c7fa6e889d902811c93614203565b936ff3392b0822b70005940c7a398e4b70f302811c936141f9565b936ff987a7253ac413176f2b074cf7815e5402811c936141ef565b936ffcbe86c7900a88aedcffc83b479aa3a402811c936141e5565b936ffe5dee046a99a2a811c461f1969c305302811c936141db565b926fff2ea16466c96a3843ec78b326b528610260801c926141d0565b926fff973b41fa98c081472e6896dfb254c00260801c926141c7565b926fffcb9843d60f6159c9db58835c9266440260801c926141be565b926fffe5caca7e10e4e61c3624eaa0941cd00260801c926141b5565b926ffff2e50f5f656932ef12357cf3c7fdcc0260801c926141ac565b926ffff97272373d413259a46990580e213a0260801c926141a3565b70ffffffffffffffffffffffffffffffffff700100000000000000000000000000000000614198565b60046040517f2bc80f3a000000000000000000000000000000000000000000000000000000008152fd5b81614161565b63ffffffff80911660005260646020526020600360406000200154916024604051809481937fdd86c1010000000000000000000000000000000000000000000000000000000083528160301c16600483015260601c5afa90811561456d575b600091614555575090565b6114fe915060203d81116109d9576109ca8183610816565b614575612f42565b61454a565b600160e01b81116145a6577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b602490604051907f1ba344530000000000000000000000000000000000000000000000000000000082526004820152fd5b600160ff1b81146145e9575b60000390565b6145f161323d565b6145e3565b60008113156146025790565b6114fe906145d7565b8015614619575b6000190490565b614621613254565b614612565b60405190614633826107fa565b600282526040366020840137565b81601f8201121561000e578051916146588361230f565b926146666040519485610816565b808452602092838086019260051b82010192831161000e578301905b828210614690575050505090565b838091835161469e81610668565b815201910190614682565b91909160408184031261000e5780519267ffffffffffffffff9384811161000e5782019381601f8601121561000e578451946146e48661230f565b906146f26040519283610816565b868252602096878084019160051b8301019185831161000e578801905b82821061472e575050509483015190811161000e576114fe9201614641565b81518060060b810361000e57815290880190880161470f565b6020908160408183019282815285518094520193019160005b82811061476e575050505090565b835163ffffffff1685529381019392810192600101614760565b60060b9060060b906000821282667fffffffffffff190182128115166147be575b82667fffffffffffff01821316613d62570390565b6147c661323d565b6147a9565b60060b9060060b9081156147ff575b6000198214667fffffffffffff198214166147f3570590565b6147fb61323d565b0590565b614807613254565b6147da565b9060060b90811561481f575b60060b0790565b614827613254565b614818565b6000199060020b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000081146135dc570190565b908160e091031261000e57805161487481610668565b91602082015161488381611529565b916040810151614892816129ec565b9160608201516148a1816129ec565b9160808101516148b0816129ec565b9160a082015160ff8116810361000e5760c0909201516114fe81610854565b9063ffffffff81168015614a6e5761494e6001600160a01b03936149096148f4614626565b946148fe86613b56565b9063ffffffff169052565b60009485918261491887613b6c565b521693604051809381927f883bdbfd00000000000000000000000000000000000000000000000000000000835260048301614747565b0381865afa849181614a49575b506149ca57505060e060049160405192838092633850c7bd60e01b82525afa9182156149bd575b9161498b575090565b6149ac915060e03d81116149b6575b6149a48183610816565b81019061485e565b5050505050905090565b503d61499a565b6149c5612f42565b614982565b6149f59192506149ef6149e26149e96149e284613b6c565b5160060b90565b92613b56565b90614788565b9060060b614a0c614a0682846147cb565b60020b90565b928260060b129182614a2b575b5050614a225790565b6114fe9061482c565b614a40925090614a3a9161480c565b60060b90565b15153880614a19565b614a669192503d8087833e614a5e8183610816565b8101906146a9565b50903861495b565b50506114fe9060e06001600160a01b0391600460405180948193633850c7bd60e01b8352165afa908115614aa8575b60009161498b575090565b614ab0612f42565b614a9d565b919091614ac860ff610170541615613585565b6000821290614ad782856158e1565b9373__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__91823b1561000e5760405163f5a284a160e01b8152600481019190915263ffffffff919091166024820152604481018490526064808201526000608482018190529091829060a49082905af48015614b96575b614b83575b506000821315614b64575061168861068792546001600160a01b031690565b614b6c575050565b6116bf6116b961068793546001600160a01b031690565b80610d4b614b90926107a1565b38614b45565b614b9e612f42565b614b40565b909261068793604051937f23b872dd0000000000000000000000000000000000000000000000000000000060208601526001600160a01b03809216602486015216604484015260648301526064825260a0820182811067ffffffffffffffff821117612fb457604052613072565b614c2160ff610170541615613585565b8115611d315773__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__803b1561000e576040517fd25c4a6f000000000000000000000000000000000000000000000000000000008152600481019290925260248201839052606460448301819052600090830181905290829060849082905af48015614ceb575b614cd8575b506000811315614cbf57610687906116886067546001600160a01b031690565b610687906116bf6116b96067546001600160a01b031690565b80610d4b614ce5926107a1565b38614c9f565b614cf3612f42565b614c9a565b90606091939293614d0f60ff610170541615613585565b614d188261598c565b828501516001600160a01b031680614dd1575b50614d6360405195869384937fc27789d100000000000000000000000000000000000000000000000000000000855260048501614eb9565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af48015614dc4575b60009081938291614d9e575b50606c54811061222a57509190565b915050614dba91925060603d811161228a576122798183610816565b9291909238614d8f565b614dcc612f42565b614d83565b614de4906122b1608088015161ffff1690565b38614d2b565b9081606091031261000e578051916040602083015192015190565b906003821015613ad55752565b614eaa60e061016093969563ffffffff610687966101808601998652166020850152805160020b6040850152602081015160020b60608501526040810151600f0b6080850152614e72606082015160a08601906001600160a01b03169052565b608081015161ffff1660c085015260a0810151151584830152614e9e60c0820151610100860190614e05565b01511515610120830152565b60646101408201520160019052565b614f1860e061016093969563ffffffff6000966101808601998652166020850152805160020b6040850152602081015160020b60608501526040810151600f0b6080850152614e72606082015160a08601906001600160a01b03169052565b60646101408201520152565b9082939291614f3960ff610170541615613585565b614f428261598c565b6040918291614fdb835195869384937f140cf61e00000000000000000000000000000000000000000000000000000000855260048501608061010092959463ffffffff6000956101208501988552166020840152805160408401526001600160a01b03602082015116606084015260408101511515828401526060810151151560a08401520151151560c0820152606460e08201520152565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af49384156150f1575b60009283956150cc575b50615010856145f6565b606c54811061192f57506001600160a01b0361503660208301516001600160a01b031690565b161515806150b6575b61504a575b50509190565b818101906150588251151590565b918261509a575b8215615073575b50501561189b5780615044565b5115915081615085575b503880615066565b90506150936118ef846145f6565b143861507d565b91506150a5866145f6565b6150af82516145f6565b149161505f565b506150c76118ce6060830151151590565b61503f565b909450816150e79293503d841161198f5761197d8183610816565b9190919338615006565b6150f9612f42565b614ffc565b919082604091031261000e576020825192015190565b608061010092959463ffffffff610687956101208501988552166020840152805160408401526001600160a01b03602082015116606084015260408101511515828401526060810151151560a08401520151151560c0820152606460e08201520160019052565b61518b60ff610170541615613585565b6151e560606151a48360005260d3602052604060002090565b604051809381927fdf19bf09000000000000000000000000000000000000000000000000000000008352600483016020606491939293604081019481520152565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af49182156152e7575b600092839284916152c1575b5061521d83856152f4565b92600085131561528f57907f688f0846fe2852572c467d5e769db101b0fea55e8849406d85c9fb322b95299b91615267866152606067546001600160a01b031690565b3390612f4f565b61527081615565565b604080519586526020860187905285015260608401523392608090a390565b6040517fef37dcc700000000000000000000000000000000000000000000000000000000815260048101869052602490fd5b919350506152dd915060603d811161228a576122798183610816565b9192909138615212565b6152ef612f42565b615206565b60008112817f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038313811516615337575b81600160ff1b038312166135dc570190565b61533f61323d565b615325565b6153c39161536e60409261535e60ff610170541615613585565b60005260d3602052604060002090565b6153778261598c565b825193849283927fec1464960000000000000000000000000000000000000000000000000000000084526004840160409063ffffffff6064939594606083019683521660208201520152565b038173__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__5af48015615468575b6000918291615448575b506000821315615416576114fe90615411836152606067546001600160a01b031690565b615565565b6040517fef37dcc700000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b9050615462915060403d811161198f5761197d8183610816565b386153ed565b615470612f42565b6153e3565b9290919261548960ff610170541615613585565b60005260d36020526040600020916154a08161598c565b606b549373__$86182d6e9eac51236f2aa8dd2a3ddeab6c$__93843b1561000e5763ffffffff9460009460c49360405197889687957fe0448f0a000000000000000000000000000000000000000000000000000000008752600487015216602485015260020b604484015260020b6064830152866084830152606460a48301525af48015615558575b615545575b506114fe816152606067546001600160a01b031690565b80610d4b615552926107a1565b3861552e565b615560612f42565b615529565b600081131561558a57610687906001600160a01b0380606754169060d5541690612f4f565b61559f6001600160a01b0360d55416916145d7565b813b1561000e576000916024839260405194859384927f379607f500000000000000000000000000000000000000000000000000000000845260048401525af180156155f6575b6155ed5750565b610687906107a1565b6155fe612f42565b6155e6565b61565a602060016001600160a01b03936156368587511682906001600160a01b03166001600160a01b0319825416179055565b019301519182511683906001600160a01b03166001600160a01b0319825416179055565b6020810151907fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff77ffffffff000000000000000000000000000000000000000078ff00000000000000000000000000000000000000000000000060408654940151151560c01b169360a01b16911617179055565b919063ffffffff83166001600160a01b03841615615864576157166118ce611a356157098463ffffffff166000526065602052604060002090565b546001600160a01b031690565b80615829575b6157c957926157807f52983c04d8ccd4808cd0fcb24e6e48106ecb41e803d6270c6c94a15e3ebd08d2939461577b615752610839565b6001600160a01b03851681529185602084015263ffffffff166000526065602052604060002090565b615603565b6157c460405192839283909291604060609160808401956001600160a01b038091168552815116602085015263ffffffff6020820151168285015201511515910152565b0390a1565b6157e7615709859263ffffffff166000526065602052604060002090565b6040517fa5d4d0b50000000000000000000000000000000000000000000000000000000081526001600160a01b03928316600482015291166024820152604490fd5b5061585f6118ce8561584e6157098563ffffffff166000526065602052604060002090565b6001600160a01b0390811691161490565b61571c565b6040517f76d8a93100000000000000000000000000000000000000000000000000000000815260006004820152602490fd5b60005260d3602052604060002090815460601c33036158b157565b60246040517f0504a20d000000000000000000000000000000000000000000000000000000008152336004820152fd5b63ffffffff90929192168060005260656020526040600020926001600160a01b038454161561595b571580615949575b6159185750565b602490604051907f9150f8c80000000000000000000000000000000000000000000000000000000082526004820152fd5b5060ff600184015460c01c1615615911565b602482604051907f6b9c1a9d0000000000000000000000000000000000000000000000000000000082526004820152fd5b63ffffffff1680600052606460205260406000206001600160a01b03815416156159f3576003015460501c60ff16156159c25750565b602490604051907fb0fdd2020000000000000000000000000000000000000000000000000000000082526004820152fd5b602482604051907fb842f5a70000000000000000000000000000000000000000000000000000000082526004820152fd5b6001600160a01b039182169116818110613d62570390565b6001600160a01b039182809216918291169204821181151516615a5d570290565b615a6561323d565b0290565b63ffffffff166000526064602052615aee6111de615add6001600160a01b039361ffff600460e0876001604060002001541660405192838092633850c7bd60e01b82525afa908115615b55575b600091615b31575b50828781168289161115615b2157615ad591615a24565b965b16615a3c565b6001600160a01b0361271091160490565b911611615af757565b60046040517f07a1db07000000000000000000000000000000000000000000000000000000008152fd5b90615b2b91615a24565b96615ad7565b615b49915060e03d81116149b6576149a48183610816565b50505050505038615abe565b615b5d612f42565b615ab6565b615b6a613fe9565b9063ffffffff91828216600052606d60205260406000209280845416911614600014615bb65750600101547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6114fe91506144eb565b615bc8613fe9565b9063ffffffff808216600052606d60205280604060002054931690831614600014615bf4575060201c90565b6114fe9150613dc39061410a565b805160051b810160209081018183015b818110615c1f5750505090565b80515481528201615c12565b9091615c4492811015615c48575b60051b810190613ae0565b9091565b615c50612d0d565b615c39565b908092918237016000815290565b60208183031261000e5780519067ffffffffffffffff821161000e570181601f8201121561000e578051615c9681612fc1565b92615ca46040519485610816565b8184526020828401011161000e576114fe9160208085019101610b5456fea2646970667358221220ce0c9dd12d7cf9ac7f88003d50982dae4b671420307d28b4df67edd28c55ad5464736f6c634300080e0033", "libraries": { - "Account": "0x3FaB135e76c5c0E85A60bf50f100c8cd912f7E56" + "Account": "0x3fab135e76c5c0e85a60bf50f100c8cd912f7e56" }, "devdoc": { "errors": { @@ -2537,6 +2544,9 @@ }, "withdrawProtocolFee(uint256)": { "notice": "withdraws protocol fees collected in the supplied wrappers to team multisig" + }, + "withdrawUSDCToTeamMultisig()": { + "notice": "WITHDRAWAL FUNCTION" } }, "version": 1 @@ -2544,7 +2554,7 @@ "storageLayout": { "storage": [ { - "astId": 26758, + "astId": 26769, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots1", "offset": 0, @@ -2552,15 +2562,15 @@ "type": "t_array(t_uint256)100_storage" }, { - "astId": 26761, + "astId": 26772, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "protocol", "offset": 0, "slot": "100", - "type": "t_struct(Info)17645_storage" + "type": "t_struct(Info)17632_storage" }, { - "astId": 26763, + "astId": 26774, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "numAccounts", "offset": 0, @@ -2568,15 +2578,15 @@ "type": "t_uint256" }, { - "astId": 26768, + "astId": 26779, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "accounts", "offset": 0, "slot": "211", - "type": "t_mapping(t_uint256,t_struct(Info)13042_storage)" + "type": "t_mapping(t_uint256,t_struct(Info)13029_storage)" }, { - "astId": 26770, + "astId": 26781, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "rageTradeFactoryAddress", "offset": 0, @@ -2584,7 +2594,7 @@ "type": "t_address" }, { - "astId": 26773, + "astId": 26784, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "insuranceFund", "offset": 0, @@ -2592,31 +2602,31 @@ "type": "t_contract(IInsuranceFund)11389" }, { - "astId": 26776, + "astId": 26787, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "pauseLoop", "offset": 0, "slot": "214", - "type": "t_struct(Info)14472_storage" + "type": "t_struct(Info)14459_storage" }, { - "astId": 26779, + "astId": 26790, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "unpauseLoop", "offset": 0, "slot": "215", - "type": "t_struct(Info)14472_storage" + "type": "t_struct(Info)14459_storage" }, { - "astId": 26782, + "astId": 26793, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "withdrawProtocolFeeLoop", "offset": 0, "slot": "216", - "type": "t_struct(Info)14472_storage" + "type": "t_struct(Info)14459_storage" }, { - "astId": 26786, + "astId": 26797, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots2", "offset": 0, @@ -2664,7 +2674,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 35294, + "astId": 35305, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_governance", "offset": 0, @@ -2672,7 +2682,7 @@ "type": "t_address" }, { - "astId": 35296, + "astId": 35307, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_teamMultisig", "offset": 0, @@ -2680,7 +2690,7 @@ "type": "t_address" }, { - "astId": 35298, + "astId": 35309, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_governancePending", "offset": 0, @@ -2688,7 +2698,7 @@ "type": "t_address" }, { - "astId": 35300, + "astId": 35311, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_teamMultisigPending", "offset": 0, @@ -2793,12 +2803,12 @@ "label": "int256", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Info)13042_storage)": { + "t_mapping(t_uint256,t_struct(Info)13029_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct Account.Info)", "numberOfBytes": "32", - "value": "t_struct(Info)13042_storage" + "value": "t_struct(Info)13029_storage" }, "t_mapping(t_uint32,t_struct(Collateral)11995_storage)": { "encoding": "mapping", @@ -2807,12 +2817,12 @@ "numberOfBytes": "32", "value": "t_struct(Collateral)11995_storage" }, - "t_mapping(t_uint32,t_struct(Info)21337_storage)": { + "t_mapping(t_uint32,t_struct(Info)21324_storage)": { "encoding": "mapping", "key": "t_uint32", "label": "mapping(uint32 => struct VTokenPosition.Info)", "numberOfBytes": "32", - "value": "t_struct(Info)21337_storage" + "value": "t_struct(Info)21324_storage" }, "t_mapping(t_uint32,t_struct(Pool)12083_storage)": { "encoding": "mapping", @@ -2821,12 +2831,12 @@ "numberOfBytes": "32", "value": "t_struct(Pool)12083_storage" }, - "t_mapping(t_uint32,t_struct(PriceCache)17607_storage)": { + "t_mapping(t_uint32,t_struct(PriceCache)17594_storage)": { "encoding": "mapping", "key": "t_uint32", "label": "mapping(uint32 => struct Protocol.PriceCache)", "numberOfBytes": "32", - "value": "t_struct(PriceCache)17607_storage" + "value": "t_struct(PriceCache)17594_storage" }, "t_mapping(t_uint32,t_uint256)": { "encoding": "mapping", @@ -2835,12 +2845,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_mapping(t_uint48,t_struct(Info)15527_storage)": { + "t_mapping(t_uint48,t_struct(Info)15514_storage)": { "encoding": "mapping", "key": "t_uint48", "label": "mapping(uint48 => struct LiquidityPosition.Info)", "numberOfBytes": "32", - "value": "t_struct(Info)15527_storage" + "value": "t_struct(Info)15514_storage" }, "t_struct(Collateral)11995_storage": { "encoding": "inplace", @@ -2896,12 +2906,12 @@ ], "numberOfBytes": "32" }, - "t_struct(Info)13042_storage": { + "t_struct(Info)13029_storage": { "encoding": "inplace", "label": "struct Account.Info", "members": [ { - "astId": 13029, + "astId": 13016, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "id", "offset": 0, @@ -2909,7 +2919,7 @@ "type": "t_uint96" }, { - "astId": 13031, + "astId": 13018, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "owner", "offset": 12, @@ -2917,23 +2927,23 @@ "type": "t_address" }, { - "astId": 13034, + "astId": 13021, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "tokenPositions", "offset": 0, "slot": "1", - "type": "t_struct(Set)21323_storage" + "type": "t_struct(Set)21310_storage" }, { - "astId": 13037, + "astId": 13024, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "collateralDeposits", "offset": 0, "slot": "104", - "type": "t_struct(Set)14796_storage" + "type": "t_struct(Set)14783_storage" }, { - "astId": 13041, + "astId": 13028, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots", "offset": 0, @@ -2943,12 +2953,12 @@ ], "numberOfBytes": "9792" }, - "t_struct(Info)14472_storage": { + "t_struct(Info)14459_storage": { "encoding": "inplace", "label": "struct BatchedLoop.Info", "members": [ { - "astId": 14471, + "astId": 14458, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "progress", "offset": 0, @@ -2958,12 +2968,12 @@ ], "numberOfBytes": "32" }, - "t_struct(Info)15527_storage": { + "t_struct(Info)15514_storage": { "encoding": "inplace", "label": "struct LiquidityPosition.Info", "members": [ { - "astId": 15506, + "astId": 15493, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "limitOrderType", "offset": 0, @@ -2971,7 +2981,7 @@ "type": "t_enum(LimitOrderType)11856" }, { - "astId": 15508, + "astId": 15495, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "tickLower", "offset": 1, @@ -2979,7 +2989,7 @@ "type": "t_int24" }, { - "astId": 15510, + "astId": 15497, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "tickUpper", "offset": 4, @@ -2987,7 +2997,7 @@ "type": "t_int24" }, { - "astId": 15512, + "astId": 15499, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "liquidity", "offset": 7, @@ -2995,7 +3005,7 @@ "type": "t_uint128" }, { - "astId": 15514, + "astId": 15501, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "vTokenAmountIn", "offset": 0, @@ -3003,7 +3013,7 @@ "type": "t_int256" }, { - "astId": 15516, + "astId": 15503, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "sumALastX128", "offset": 0, @@ -3011,7 +3021,7 @@ "type": "t_int256" }, { - "astId": 15518, + "astId": 15505, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "sumBInsideLastX128", "offset": 0, @@ -3019,7 +3029,7 @@ "type": "t_int256" }, { - "astId": 15520, + "astId": 15507, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "sumFpInsideLastX128", "offset": 0, @@ -3027,7 +3037,7 @@ "type": "t_int256" }, { - "astId": 15522, + "astId": 15509, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "sumFeeInsideLastX128", "offset": 0, @@ -3035,7 +3045,7 @@ "type": "t_uint256" }, { - "astId": 15526, + "astId": 15513, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots", "offset": 0, @@ -3045,12 +3055,12 @@ ], "numberOfBytes": "3392" }, - "t_struct(Info)17645_storage": { + "t_struct(Info)17632_storage": { "encoding": "inplace", "label": "struct Protocol.Info", "members": [ { - "astId": 17612, + "astId": 17599, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "pools", "offset": 0, @@ -3058,7 +3068,7 @@ "type": "t_mapping(t_uint32,t_struct(Pool)12083_storage)" }, { - "astId": 17617, + "astId": 17604, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "collaterals", "offset": 0, @@ -3066,7 +3076,7 @@ "type": "t_mapping(t_uint32,t_struct(Collateral)11995_storage)" }, { - "astId": 17620, + "astId": 17607, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "poolIds", "offset": 0, @@ -3074,7 +3084,7 @@ "type": "t_array(t_uint32)dyn_storage" }, { - "astId": 17623, + "astId": 17610, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "settlementToken", "offset": 0, @@ -3082,7 +3092,7 @@ "type": "t_contract(IERC20)4189" }, { - "astId": 17626, + "astId": 17613, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "vQuote", "offset": 0, @@ -3090,7 +3100,7 @@ "type": "t_contract(IVQuote)11632" }, { - "astId": 17629, + "astId": 17616, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "liquidationParams", "offset": 0, @@ -3098,7 +3108,7 @@ "type": "t_struct(LiquidationParams)12064_storage" }, { - "astId": 17631, + "astId": 17618, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "minRequiredMargin", "offset": 0, @@ -3106,7 +3116,7 @@ "type": "t_uint256" }, { - "astId": 17633, + "astId": 17620, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "removeLimitOrderFee", "offset": 0, @@ -3114,7 +3124,7 @@ "type": "t_uint256" }, { - "astId": 17635, + "astId": 17622, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "minimumOrderNotional", "offset": 0, @@ -3122,15 +3132,15 @@ "type": "t_uint256" }, { - "astId": 17640, + "astId": 17627, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "priceCache", "offset": 0, "slot": "9", - "type": "t_mapping(t_uint32,t_struct(PriceCache)17607_storage)" + "type": "t_mapping(t_uint32,t_struct(PriceCache)17594_storage)" }, { - "astId": 17644, + "astId": 17631, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots", "offset": 0, @@ -3140,12 +3150,12 @@ ], "numberOfBytes": "3520" }, - "t_struct(Info)21337_storage": { + "t_struct(Info)21324_storage": { "encoding": "inplace", "label": "struct VTokenPosition.Info", "members": [ { - "astId": 21325, + "astId": 21312, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "balance", "offset": 0, @@ -3153,7 +3163,7 @@ "type": "t_int256" }, { - "astId": 21327, + "astId": 21314, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "netTraderPosition", "offset": 0, @@ -3161,7 +3171,7 @@ "type": "t_int256" }, { - "astId": 21329, + "astId": 21316, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "sumALastX128", "offset": 0, @@ -3169,15 +3179,15 @@ "type": "t_int256" }, { - "astId": 21332, + "astId": 21319, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "liquidityPositions", "offset": 0, "slot": "3", - "type": "t_struct(Set)15503_storage" + "type": "t_struct(Set)15490_storage" }, { - "astId": 21336, + "astId": 21323, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots", "offset": 0, @@ -3360,12 +3370,12 @@ ], "numberOfBytes": "32" }, - "t_struct(PriceCache)17607_storage": { + "t_struct(PriceCache)17594_storage": { "encoding": "inplace", "label": "struct Protocol.PriceCache", "members": [ { - "astId": 17600, + "astId": 17587, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "updateBlockNumber", "offset": 0, @@ -3373,7 +3383,7 @@ "type": "t_uint32" }, { - "astId": 17602, + "astId": 17589, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "virtualPriceX128", "offset": 4, @@ -3381,7 +3391,7 @@ "type": "t_uint224" }, { - "astId": 17604, + "astId": 17591, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "realPriceX128", "offset": 0, @@ -3389,7 +3399,7 @@ "type": "t_uint224" }, { - "astId": 17606, + "astId": 17593, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "isDeviationBreached", "offset": 28, @@ -3399,12 +3409,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Set)14796_storage": { + "t_struct(Set)14783_storage": { "encoding": "inplace", "label": "struct CollateralDeposit.Set", "members": [ { - "astId": 14787, + "astId": 14774, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "active", "offset": 0, @@ -3412,7 +3422,7 @@ "type": "t_array(t_uint32)8_storage" }, { - "astId": 14791, + "astId": 14778, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "deposits", "offset": 0, @@ -3420,7 +3430,7 @@ "type": "t_mapping(t_uint32,t_uint256)" }, { - "astId": 14795, + "astId": 14782, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots", "offset": 0, @@ -3430,12 +3440,12 @@ ], "numberOfBytes": "3264" }, - "t_struct(Set)15503_storage": { + "t_struct(Set)15490_storage": { "encoding": "inplace", "label": "struct LiquidityPosition.Set", "members": [ { - "astId": 15493, + "astId": 15480, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "active", "offset": 0, @@ -3443,15 +3453,15 @@ "type": "t_array(t_uint48)5_storage" }, { - "astId": 15498, + "astId": 15485, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "positions", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint48,t_struct(Info)15527_storage)" + "type": "t_mapping(t_uint48,t_struct(Info)15514_storage)" }, { - "astId": 15502, + "astId": 15489, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots", "offset": 0, @@ -3461,12 +3471,12 @@ ], "numberOfBytes": "3264" }, - "t_struct(Set)21323_storage": { + "t_struct(Set)21310_storage": { "encoding": "inplace", "label": "struct VTokenPosition.Set", "members": [ { - "astId": 21311, + "astId": 21298, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "active", "offset": 0, @@ -3474,15 +3484,15 @@ "type": "t_array(t_uint32)8_storage" }, { - "astId": 21316, + "astId": 21303, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "positions", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint32,t_struct(Info)21337_storage)" + "type": "t_mapping(t_uint32,t_struct(Info)21324_storage)" }, { - "astId": 21318, + "astId": 21305, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "vQuoteBalance", "offset": 0, @@ -3490,7 +3500,7 @@ "type": "t_int256" }, { - "astId": 21322, + "astId": 21309, "contract": "contracts/protocol/clearinghouse/ClearingHouse.sol:ClearingHouse", "label": "_emptySlots", "offset": 0, diff --git a/deployments/arbmain/solcInputs/22b7028cc81d5cf62f774cbaec4dae64.json b/deployments/arbmain/solcInputs/22b7028cc81d5cf62f774cbaec4dae64.json new file mode 100644 index 00000000..4916ab2d --- /dev/null +++ b/deployments/arbmain/solcInputs/22b7028cc81d5cf62f774cbaec4dae64.json @@ -0,0 +1,537 @@ +{ + "language": "Solidity", + "sources": { + "contracts/extsloads/ClearingHouseExtsload.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { IClearingHouse } from '../interfaces/IClearingHouse.sol';\nimport { IExtsload } from '../interfaces/IExtsload.sol';\nimport { IOracle } from '../interfaces/IOracle.sol';\nimport { IVQuote } from '../interfaces/IVQuote.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\n\nimport { Uint48Lib } from '../libraries/Uint48.sol';\nimport { WordHelper } from '../libraries/WordHelper.sol';\n\nlibrary ClearingHouseExtsload {\n // Terminology:\n // SLOT is a storage location value which can be sloaded, typed in bytes32.\n // OFFSET is an slot offset value which should not be sloaded, henced typed in uint256.\n\n using WordHelper for bytes32;\n using WordHelper for WordHelper.Word;\n\n /**\n * PROTOCOL\n */\n\n bytes32 constant PROTOCOL_SLOT = bytes32(uint256(100));\n uint256 constant PROTOCOL_POOLS_MAPPING_OFFSET = 0;\n uint256 constant PROTOCOL_COLLATERALS_MAPPING_OFFSET = 1;\n uint256 constant PROTOCOL_SETTLEMENT_TOKEN_OFFSET = 3;\n uint256 constant PROTOCOL_VQUOTE_OFFSET = 4;\n uint256 constant PROTOCOL_LIQUIDATION_PARAMS_STRUCT_OFFSET = 5;\n uint256 constant PROTOCOL_MINIMUM_REQUIRED_MARGIN_OFFSET = 6;\n uint256 constant PROTOCOL_REMOVE_LIMIT_ORDER_FEE_OFFSET = 7;\n uint256 constant PROTOCOL_MINIMUM_ORDER_NOTIONAL_OFFSET = 8;\n\n function _decodeLiquidationParamsSlot(bytes32 data)\n internal\n pure\n returns (IClearingHouse.LiquidationParams memory liquidationParams)\n {\n WordHelper.Word memory result = data.copyToMemory();\n liquidationParams.rangeLiquidationFeeFraction = result.popUint16();\n liquidationParams.tokenLiquidationFeeFraction = result.popUint16();\n liquidationParams.closeFactorMMThresholdBps = result.popUint16();\n liquidationParams.partialLiquidationCloseFactorBps = result.popUint16();\n liquidationParams.insuranceFundFeeShareBps = result.popUint16();\n liquidationParams.liquidationSlippageSqrtToleranceBps = result.popUint16();\n liquidationParams.maxRangeLiquidationFees = result.popUint64();\n liquidationParams.minNotionalLiquidatable = result.popUint64();\n }\n\n /// @notice Gets the protocol info, global protocol settings\n /// @return settlementToken the token in which profit is settled\n /// @return vQuote the vQuote token contract\n /// @return liquidationParams the liquidation parameters\n /// @return minRequiredMargin minimum required margin an account has to keep with non-zero netPosition\n /// @return removeLimitOrderFee the fee charged for using removeLimitOrder service\n /// @return minimumOrderNotional the minimum order notional\n function getProtocolInfo(IClearingHouse clearingHouse)\n internal\n view\n returns (\n IERC20 settlementToken,\n IVQuote vQuote,\n IClearingHouse.LiquidationParams memory liquidationParams,\n uint256 minRequiredMargin,\n uint256 removeLimitOrderFee,\n uint256 minimumOrderNotional\n )\n {\n bytes32[] memory arr = new bytes32[](6);\n arr[0] = PROTOCOL_SLOT.offset(PROTOCOL_SETTLEMENT_TOKEN_OFFSET);\n arr[1] = PROTOCOL_SLOT.offset(PROTOCOL_VQUOTE_OFFSET);\n arr[2] = PROTOCOL_SLOT.offset(PROTOCOL_LIQUIDATION_PARAMS_STRUCT_OFFSET);\n arr[3] = PROTOCOL_SLOT.offset(PROTOCOL_MINIMUM_REQUIRED_MARGIN_OFFSET);\n arr[4] = PROTOCOL_SLOT.offset(PROTOCOL_REMOVE_LIMIT_ORDER_FEE_OFFSET);\n arr[5] = PROTOCOL_SLOT.offset(PROTOCOL_MINIMUM_ORDER_NOTIONAL_OFFSET);\n arr = clearingHouse.extsload(arr);\n settlementToken = IERC20(arr[0].toAddress());\n vQuote = IVQuote(arr[1].toAddress());\n liquidationParams = _decodeLiquidationParamsSlot(arr[2]);\n minRequiredMargin = arr[3].toUint256();\n removeLimitOrderFee = arr[4].toUint256();\n minimumOrderNotional = arr[5].toUint256();\n }\n\n /**\n * PROTOCOL POOLS MAPPING\n */\n\n uint256 constant POOL_VTOKEN_OFFSET = 0;\n uint256 constant POOL_VPOOL_OFFSET = 1;\n uint256 constant POOL_VPOOLWRAPPER_OFFSET = 2;\n uint256 constant POOL_SETTINGS_STRUCT_OFFSET = 3;\n\n function poolStructSlot(uint32 poolId) internal pure returns (bytes32) {\n return\n WordHelper.keccak256Two({\n mappingSlot: PROTOCOL_SLOT.offset(PROTOCOL_POOLS_MAPPING_OFFSET),\n paddedKey: WordHelper.fromUint(poolId)\n });\n }\n\n function _decodePoolSettingsSlot(bytes32 data) internal pure returns (IClearingHouse.PoolSettings memory settings) {\n WordHelper.Word memory result = data.copyToMemory();\n settings.initialMarginRatioBps = result.popUint16();\n settings.maintainanceMarginRatioBps = result.popUint16();\n settings.maxVirtualPriceDeviationRatioBps = result.popUint16();\n settings.twapDuration = result.popUint32();\n settings.isAllowedForTrade = result.popBool();\n settings.isCrossMargined = result.popBool();\n settings.oracle = IOracle(result.popAddress());\n }\n\n /// @notice Gets the info about a supported pool in the protocol\n /// @param poolId the id of the pool\n /// @return pool the Pool struct\n function getPoolInfo(IClearingHouse clearingHouse, uint32 poolId)\n internal\n view\n returns (IClearingHouse.Pool memory pool)\n {\n bytes32 POOL_SLOT = poolStructSlot(poolId);\n bytes32[] memory arr = new bytes32[](4);\n arr[0] = POOL_SLOT; // POOL_VTOKEN_OFFSET\n arr[1] = POOL_SLOT.offset(POOL_VPOOL_OFFSET);\n arr[2] = POOL_SLOT.offset(POOL_VPOOLWRAPPER_OFFSET);\n arr[3] = POOL_SLOT.offset(POOL_SETTINGS_STRUCT_OFFSET);\n arr = clearingHouse.extsload(arr);\n pool.vToken = IVToken(arr[0].toAddress());\n pool.vPool = IUniswapV3Pool(arr[1].toAddress());\n pool.vPoolWrapper = IVPoolWrapper(arr[2].toAddress());\n pool.settings = _decodePoolSettingsSlot(arr[3]);\n }\n\n function getVPool(IClearingHouse clearingHouse, uint32 poolId) internal view returns (IUniswapV3Pool vPool) {\n bytes32 result = clearingHouse.extsload(poolStructSlot(poolId).offset(POOL_VPOOL_OFFSET));\n assembly {\n vPool := result\n }\n }\n\n function getPoolSettings(IClearingHouse clearingHouse, uint32 poolId)\n internal\n view\n returns (IClearingHouse.PoolSettings memory)\n {\n bytes32 SETTINGS_SLOT = poolStructSlot(poolId).offset(POOL_SETTINGS_STRUCT_OFFSET);\n return _decodePoolSettingsSlot(clearingHouse.extsload(SETTINGS_SLOT));\n }\n\n function getTwapDuration(IClearingHouse clearingHouse, uint32 poolId) internal view returns (uint32 twapDuration) {\n bytes32 result = clearingHouse.extsload(poolStructSlot(poolId).offset(POOL_SETTINGS_STRUCT_OFFSET));\n twapDuration = result.slice(0x30, 0x50).toUint32();\n }\n\n function getVPoolAndTwapDuration(IClearingHouse clearingHouse, uint32 poolId)\n internal\n view\n returns (IUniswapV3Pool vPool, uint32 twapDuration)\n {\n bytes32[] memory arr = new bytes32[](2);\n\n bytes32 POOL_SLOT = poolStructSlot(poolId);\n arr[0] = POOL_SLOT.offset(POOL_VPOOL_OFFSET); // vPool\n arr[1] = POOL_SLOT.offset(POOL_SETTINGS_STRUCT_OFFSET); // settings\n arr = clearingHouse.extsload(arr);\n\n vPool = IUniswapV3Pool(arr[0].toAddress());\n twapDuration = arr[1].slice(0xB0, 0xD0).toUint32();\n }\n\n /// @notice Checks if a poolId is unused\n /// @param poolId the id of the pool\n /// @return true if the poolId is unused, false otherwise\n function isPoolIdAvailable(IClearingHouse clearingHouse, uint32 poolId) internal view returns (bool) {\n bytes32 VTOKEN_SLOT = poolStructSlot(poolId).offset(POOL_VTOKEN_OFFSET);\n bytes32 result = clearingHouse.extsload(VTOKEN_SLOT);\n return result == WordHelper.fromUint(0);\n }\n\n /**\n * PROTOCOL COLLATERALS MAPPING\n */\n\n uint256 constant COLLATERAL_TOKEN_OFFSET = 0;\n uint256 constant COLLATERAL_SETTINGS_OFFSET = 1;\n\n function collateralStructSlot(uint32 collateralId) internal pure returns (bytes32) {\n return\n WordHelper.keccak256Two({\n mappingSlot: PROTOCOL_SLOT.offset(PROTOCOL_COLLATERALS_MAPPING_OFFSET),\n paddedKey: WordHelper.fromUint(collateralId)\n });\n }\n\n function _decodeCollateralSettings(bytes32 data)\n internal\n pure\n returns (IClearingHouse.CollateralSettings memory settings)\n {\n WordHelper.Word memory result = data.copyToMemory();\n settings.oracle = IOracle(result.popAddress());\n settings.twapDuration = result.popUint32();\n settings.isAllowedForDeposit = result.popBool();\n }\n\n /// @notice Gets the info about a supported collateral in the protocol\n /// @param collateralId the id of the collateral\n /// @return collateral the Collateral struct\n function getCollateralInfo(IClearingHouse clearingHouse, uint32 collateralId)\n internal\n view\n returns (IClearingHouse.Collateral memory collateral)\n {\n bytes32[] memory arr = new bytes32[](2);\n bytes32 COLLATERAL_STRUCT_SLOT = collateralStructSlot(collateralId);\n arr[0] = COLLATERAL_STRUCT_SLOT; // COLLATERAL_TOKEN_OFFSET\n arr[1] = COLLATERAL_STRUCT_SLOT.offset(COLLATERAL_SETTINGS_OFFSET);\n arr = clearingHouse.extsload(arr);\n collateral.token = IVToken(arr[0].toAddress());\n collateral.settings = _decodeCollateralSettings(arr[1]);\n }\n\n /**\n * ACCOUNT MAPPING\n */\n bytes32 constant ACCOUNTS_MAPPING_SLOT = bytes32(uint256(211));\n uint256 constant ACCOUNT_ID_OWNER_OFFSET = 0;\n uint256 constant ACCOUNT_VTOKENPOSITIONS_ACTIVE_SET_OFFSET = 1;\n uint256 constant ACCOUNT_VTOKENPOSITIONS_MAPPING_OFFSET = 2;\n uint256 constant ACCOUNT_VQUOTE_BALANCE_OFFSET = 3;\n uint256 constant ACCOUNT_COLLATERAL_ACTIVE_SET_OFFSET = 104;\n uint256 constant ACCOUNT_COLLATERAL_MAPPING_OFFSET = 105;\n\n // VTOKEN POSITION STRUCT\n uint256 constant ACCOUNT_VTOKENPOSITION_BALANCE_OFFSET = 0;\n uint256 constant ACCOUNT_VTOKENPOSITION_NET_TRADER_POSITION_OFFSET = 1;\n uint256 constant ACCOUNT_VTOKENPOSITION_SUM_A_LAST_OFFSET = 2;\n uint256 constant ACCOUNT_VTOKENPOSITION_LIQUIDITY_ACTIVE_OFFSET = 3;\n uint256 constant ACCOUNT_VTOKENPOSITION_LIQUIDITY_MAPPING_OFFSET = 4;\n\n // LIQUIDITY POSITION STRUCT\n uint256 constant ACCOUNT_TP_LP_SLOT0_OFFSET = 0; // limit order type, tl, tu, liquidity\n uint256 constant ACCOUNT_TP_LP_VTOKEN_AMOUNTIN_OFFSET = 1;\n uint256 constant ACCOUNT_TP_LP_SUM_A_LAST_OFFSET = 2;\n uint256 constant ACCOUNT_TP_LP_SUM_B_LAST_OFFSET = 3;\n uint256 constant ACCOUNT_TP_LP_SUM_FP_LAST_OFFSET = 4;\n uint256 constant ACCOUNT_TP_LP_SUM_FEE_LAST_OFFSET = 5;\n\n function accountStructSlot(uint256 accountId) internal pure returns (bytes32) {\n return\n WordHelper.keccak256Two({ mappingSlot: ACCOUNTS_MAPPING_SLOT, paddedKey: WordHelper.fromUint(accountId) });\n }\n\n function accountCollateralStructSlot(bytes32 ACCOUNT_STRUCT_SLOT, uint32 collateralId)\n internal\n pure\n returns (bytes32)\n {\n return\n WordHelper.keccak256Two({\n mappingSlot: ACCOUNT_STRUCT_SLOT.offset(ACCOUNT_COLLATERAL_MAPPING_OFFSET),\n paddedKey: WordHelper.fromUint(collateralId)\n });\n }\n\n function accountVTokenPositionStructSlot(bytes32 ACCOUNT_STRUCT_SLOT, uint32 poolId)\n internal\n pure\n returns (bytes32)\n {\n return\n WordHelper.keccak256Two({\n mappingSlot: ACCOUNT_STRUCT_SLOT.offset(ACCOUNT_VTOKENPOSITIONS_MAPPING_OFFSET),\n paddedKey: WordHelper.fromUint(poolId)\n });\n }\n\n function accountLiquidityPositionStructSlot(\n bytes32 ACCOUNT_VTOKENPOSITION_STRUCT_SLOT,\n int24 tickLower,\n int24 tickUpper\n ) internal pure returns (bytes32) {\n return\n WordHelper.keccak256Two({\n mappingSlot: ACCOUNT_VTOKENPOSITION_STRUCT_SLOT.offset(ACCOUNT_VTOKENPOSITION_LIQUIDITY_MAPPING_OFFSET),\n paddedKey: WordHelper.fromUint(Uint48Lib.concat(tickLower, tickUpper))\n });\n }\n\n function getAccountInfo(IClearingHouse clearingHouse, uint256 accountId)\n internal\n view\n returns (\n address owner,\n int256 vQuoteBalance,\n uint32[] memory activeCollateralIds,\n uint32[] memory activePoolIds\n )\n {\n bytes32[] memory arr = new bytes32[](4);\n bytes32 ACCOUNT_SLOT = accountStructSlot(accountId);\n arr[0] = ACCOUNT_SLOT; // ACCOUNT_ID_OWNER_OFFSET\n arr[1] = ACCOUNT_SLOT.offset(ACCOUNT_VQUOTE_BALANCE_OFFSET);\n arr[2] = ACCOUNT_SLOT.offset(ACCOUNT_COLLATERAL_ACTIVE_SET_OFFSET);\n arr[3] = ACCOUNT_SLOT.offset(ACCOUNT_VTOKENPOSITIONS_ACTIVE_SET_OFFSET);\n\n arr = clearingHouse.extsload(arr);\n\n owner = arr[0].slice(0, 160).toAddress();\n vQuoteBalance = arr[1].toInt256();\n activeCollateralIds = arr[2].convertToUint32Array();\n activePoolIds = arr[3].convertToUint32Array();\n }\n\n function getAccountCollateralInfo(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 collateralId\n ) internal view returns (IERC20 collateral, uint256 balance) {\n bytes32[] memory arr = new bytes32[](2);\n arr[0] = accountCollateralStructSlot(accountStructSlot(accountId), collateralId); // ACCOUNT_COLLATERAL_BALANCE_SLOT\n arr[1] = collateralStructSlot(collateralId); // COLLATERAL_TOKEN_ADDRESS_SLOT\n\n arr = clearingHouse.extsload(arr);\n\n balance = arr[0].toUint256();\n collateral = IERC20(arr[1].toAddress());\n }\n\n function getAccountCollateralBalance(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 collateralId\n ) internal view returns (uint256 balance) {\n bytes32 COLLATERAL_BALANCE_SLOT = accountCollateralStructSlot(accountStructSlot(accountId), collateralId);\n\n balance = clearingHouse.extsload(COLLATERAL_BALANCE_SLOT).toUint256();\n }\n\n function getAccountTokenPositionInfo(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 poolId\n )\n internal\n view\n returns (\n int256 balance,\n int256 netTraderPosition,\n int256 sumALastX128\n )\n {\n bytes32 VTOKEN_POSITION_STRUCT_SLOT = accountVTokenPositionStructSlot(accountStructSlot(accountId), poolId);\n\n bytes32[] memory arr = new bytes32[](3);\n arr[0] = VTOKEN_POSITION_STRUCT_SLOT; // BALANCE\n arr[1] = VTOKEN_POSITION_STRUCT_SLOT.offset(ACCOUNT_VTOKENPOSITION_NET_TRADER_POSITION_OFFSET);\n arr[2] = VTOKEN_POSITION_STRUCT_SLOT.offset(ACCOUNT_VTOKENPOSITION_SUM_A_LAST_OFFSET);\n\n arr = clearingHouse.extsload(arr);\n\n balance = arr[0].toInt256();\n netTraderPosition = arr[1].toInt256();\n sumALastX128 = arr[2].toInt256();\n }\n\n function getAccountPositionInfo(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 poolId\n )\n internal\n view\n returns (\n int256 balance,\n int256 netTraderPosition,\n int256 sumALastX128,\n IClearingHouse.TickRange[] memory activeTickRanges\n )\n {\n bytes32 VTOKEN_POSITION_STRUCT_SLOT = accountVTokenPositionStructSlot(accountStructSlot(accountId), poolId);\n\n bytes32[] memory arr = new bytes32[](4);\n arr[0] = VTOKEN_POSITION_STRUCT_SLOT; // BALANCE\n arr[1] = VTOKEN_POSITION_STRUCT_SLOT.offset(ACCOUNT_VTOKENPOSITION_NET_TRADER_POSITION_OFFSET);\n arr[2] = VTOKEN_POSITION_STRUCT_SLOT.offset(ACCOUNT_VTOKENPOSITION_SUM_A_LAST_OFFSET);\n arr[3] = VTOKEN_POSITION_STRUCT_SLOT.offset(ACCOUNT_VTOKENPOSITION_LIQUIDITY_ACTIVE_OFFSET);\n\n arr = clearingHouse.extsload(arr);\n\n balance = arr[0].toInt256();\n netTraderPosition = arr[1].toInt256();\n sumALastX128 = arr[2].toInt256();\n activeTickRanges = arr[3].convertToTickRangeArray();\n }\n\n function getAccountLiquidityPositionList(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 poolId\n ) internal view returns (IClearingHouse.TickRange[] memory activeTickRanges) {\n return\n clearingHouse\n .extsload(\n accountVTokenPositionStructSlot(accountStructSlot(accountId), poolId).offset(\n ACCOUNT_VTOKENPOSITION_LIQUIDITY_ACTIVE_OFFSET\n )\n )\n .convertToTickRangeArray();\n }\n\n function getAccountLiquidityPositionInfo(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 poolId,\n int24 tickLower,\n int24 tickUpper\n )\n internal\n view\n returns (\n uint8 limitOrderType,\n uint128 liquidity,\n int256 vTokenAmountIn,\n int256 sumALastX128,\n int256 sumBInsideLastX128,\n int256 sumFpInsideLastX128,\n uint256 sumFeeInsideLastX128\n )\n {\n bytes32 LIQUIDITY_POSITION_STRUCT_SLOT = accountLiquidityPositionStructSlot(\n accountVTokenPositionStructSlot(accountStructSlot(accountId), poolId),\n tickLower,\n tickUpper\n );\n\n bytes32[] memory arr = new bytes32[](6);\n arr[0] = LIQUIDITY_POSITION_STRUCT_SLOT; // BALANCE\n arr[1] = LIQUIDITY_POSITION_STRUCT_SLOT.offset(ACCOUNT_TP_LP_VTOKEN_AMOUNTIN_OFFSET);\n arr[2] = LIQUIDITY_POSITION_STRUCT_SLOT.offset(ACCOUNT_TP_LP_SUM_A_LAST_OFFSET);\n arr[3] = LIQUIDITY_POSITION_STRUCT_SLOT.offset(ACCOUNT_TP_LP_SUM_B_LAST_OFFSET);\n arr[4] = LIQUIDITY_POSITION_STRUCT_SLOT.offset(ACCOUNT_TP_LP_SUM_FP_LAST_OFFSET);\n arr[5] = LIQUIDITY_POSITION_STRUCT_SLOT.offset(ACCOUNT_TP_LP_SUM_FEE_LAST_OFFSET);\n\n arr = clearingHouse.extsload(arr);\n\n WordHelper.Word memory slot0 = arr[0].copyToMemory();\n limitOrderType = slot0.popUint8();\n slot0.pop(48); // discard 48 bits\n liquidity = slot0.popUint128();\n vTokenAmountIn = arr[1].toInt256();\n sumALastX128 = arr[2].toInt256();\n sumBInsideLastX128 = arr[3].toInt256();\n sumFpInsideLastX128 = arr[4].toInt256();\n sumFeeInsideLastX128 = arr[5].toUint256();\n }\n\n function _getProtocolSlot() internal pure returns (bytes32) {\n return PROTOCOL_SLOT;\n }\n\n function _getProtocolOffsets()\n internal\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return (\n PROTOCOL_POOLS_MAPPING_OFFSET,\n PROTOCOL_COLLATERALS_MAPPING_OFFSET,\n PROTOCOL_SETTLEMENT_TOKEN_OFFSET,\n PROTOCOL_VQUOTE_OFFSET,\n PROTOCOL_LIQUIDATION_PARAMS_STRUCT_OFFSET,\n PROTOCOL_MINIMUM_REQUIRED_MARGIN_OFFSET,\n PROTOCOL_REMOVE_LIMIT_ORDER_FEE_OFFSET,\n PROTOCOL_MINIMUM_ORDER_NOTIONAL_OFFSET\n );\n }\n\n function _getPoolOffsets()\n internal\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return (POOL_VTOKEN_OFFSET, POOL_VPOOL_OFFSET, POOL_VPOOLWRAPPER_OFFSET, POOL_SETTINGS_STRUCT_OFFSET);\n }\n\n function _getCollateralOffsets() internal pure returns (uint256, uint256) {\n return (COLLATERAL_TOKEN_OFFSET, COLLATERAL_SETTINGS_OFFSET);\n }\n\n function _getAccountsMappingSlot() internal pure returns (bytes32) {\n return ACCOUNTS_MAPPING_SLOT;\n }\n\n function _getAccountOffsets()\n internal\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return (\n ACCOUNT_ID_OWNER_OFFSET,\n ACCOUNT_VTOKENPOSITIONS_ACTIVE_SET_OFFSET,\n ACCOUNT_VTOKENPOSITIONS_MAPPING_OFFSET,\n ACCOUNT_VQUOTE_BALANCE_OFFSET,\n ACCOUNT_COLLATERAL_ACTIVE_SET_OFFSET,\n ACCOUNT_COLLATERAL_MAPPING_OFFSET\n );\n }\n\n function _getVTokenPositionOffsets()\n internal\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return (\n ACCOUNT_VTOKENPOSITION_BALANCE_OFFSET,\n ACCOUNT_VTOKENPOSITION_NET_TRADER_POSITION_OFFSET,\n ACCOUNT_VTOKENPOSITION_SUM_A_LAST_OFFSET,\n ACCOUNT_VTOKENPOSITION_LIQUIDITY_ACTIVE_OFFSET,\n ACCOUNT_VTOKENPOSITION_LIQUIDITY_MAPPING_OFFSET\n );\n }\n\n function _getLiquidityPositionOffsets()\n internal\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return (\n ACCOUNT_TP_LP_SLOT0_OFFSET,\n ACCOUNT_TP_LP_VTOKEN_AMOUNTIN_OFFSET,\n ACCOUNT_TP_LP_SUM_A_LAST_OFFSET,\n ACCOUNT_TP_LP_SUM_B_LAST_OFFSET,\n ACCOUNT_TP_LP_SUM_FP_LAST_OFFSET,\n ACCOUNT_TP_LP_SUM_FEE_LAST_OFFSET\n );\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n\n /**\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" + }, + "@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IUniswapV3PoolImmutables} from './pool/IUniswapV3PoolImmutables.sol';\nimport {IUniswapV3PoolState} from './pool/IUniswapV3PoolState.sol';\nimport {IUniswapV3PoolDerivedState} from './pool/IUniswapV3PoolDerivedState.sol';\nimport {IUniswapV3PoolActions} from './pool/IUniswapV3PoolActions.sol';\nimport {IUniswapV3PoolOwnerActions} from './pool/IUniswapV3PoolOwnerActions.sol';\nimport {IUniswapV3PoolErrors} from './pool/IUniswapV3PoolErrors.sol';\nimport {IUniswapV3PoolEvents} from './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 IUniswapV3PoolErrors,\n IUniswapV3PoolEvents\n{\n\n}\n" + }, + "contracts/interfaces/IClearingHouse.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { IGovernable } from './IGovernable.sol';\n\nimport { IClearingHouseActions } from './clearinghouse/IClearingHouseActions.sol';\nimport { IClearingHouseCustomErrors } from './clearinghouse/IClearingHouseCustomErrors.sol';\nimport { IClearingHouseEnums } from './clearinghouse/IClearingHouseEnums.sol';\nimport { IClearingHouseEvents } from './clearinghouse/IClearingHouseEvents.sol';\nimport { IClearingHouseOwnerActions } from './clearinghouse/IClearingHouseOwnerActions.sol';\nimport { IClearingHouseStructures } from './clearinghouse/IClearingHouseStructures.sol';\nimport { IClearingHouseSystemActions } from './clearinghouse/IClearingHouseSystemActions.sol';\nimport { IClearingHouseView } from './clearinghouse/IClearingHouseView.sol';\n\ninterface IClearingHouse is\n IGovernable,\n IClearingHouseEnums,\n IClearingHouseStructures,\n IClearingHouseActions,\n IClearingHouseCustomErrors,\n IClearingHouseEvents,\n IClearingHouseOwnerActions,\n IClearingHouseSystemActions,\n IClearingHouseView\n{}\n" + }, + "contracts/interfaces/IExtsload.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\n/// @title This is an interface to read contract's state that supports extsload.\ninterface IExtsload {\n /// @notice Returns a value from the storage.\n /// @param slot to read from.\n /// @return value stored at the slot.\n function extsload(bytes32 slot) external view returns (bytes32 value);\n\n /// @notice Returns multiple values from storage.\n /// @param slots to read from.\n /// @return values stored at the slots.\n function extsload(bytes32[] memory slots) external view returns (bytes32[] memory);\n}\n" + }, + "contracts/interfaces/IOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface IOracle {\n function getTwapPriceX128(uint32 twapDuration) external view returns (uint256 priceX128);\n}\n" + }, + "contracts/interfaces/IVQuote.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\ninterface IVQuote is IERC20 {\n function mint(address account, uint256 amount) external;\n\n function burn(uint256 amount) external;\n\n function authorize(address vPoolWrapper) external;\n}\n" + }, + "contracts/interfaces/IVPoolWrapper.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { IVQuote } from './IVQuote.sol';\nimport { IVToken } from './IVToken.sol';\n\ninterface IVPoolWrapper {\n struct InitializeVPoolWrapperParams {\n address clearingHouse; // address of clearing house contract (proxy)\n IVToken vToken; // address of vToken contract\n IVQuote vQuote; // address of vQuote contract\n IUniswapV3Pool vPool; // address of Uniswap V3 Pool contract, created using vToken and vQuote\n uint24 liquidityFeePips; // liquidity fee fraction (in 1e6)\n uint24 protocolFeePips; // protocol fee fraction (in 1e6)\n }\n\n struct SwapResult {\n int256 amountSpecified; // amount of tokens/vQuote which were specified in the swap request\n int256 vTokenIn; // actual amount of vTokens paid by account to the Pool\n int256 vQuoteIn; // actual amount of vQuotes paid by account to the Pool\n uint256 liquidityFees; // actual amount of fees paid by account to the Pool\n uint256 protocolFees; // actual amount of fees paid by account to the Protocol\n uint160 sqrtPriceX96Start; // sqrt price at the beginning of the swap\n uint160 sqrtPriceX96End; // sqrt price at the end of the swap\n }\n\n struct WrapperValuesInside {\n int256 sumAX128; // sum of all the A terms in the pool\n int256 sumBInsideX128; // sum of all the B terms in side the tick range in the pool\n int256 sumFpInsideX128; // sum of all the Fp terms in side the tick range in the pool\n uint256 sumFeeInsideX128; // sum of all the fee terms in side the tick range in the pool\n }\n\n /// @notice Emitted whenever a swap takes place\n /// @param swapResult the swap result values\n event Swap(SwapResult swapResult);\n\n /// @notice Emitted whenever liquidity is added\n /// @param tickLower the lower tick of the range\n /// @param tickUpper the upper tick of the range\n /// @param liquidity the amount of liquidity that was added\n /// @param vTokenPrincipal the amount of vToken that was sent to UniswapV3Pool\n /// @param vQuotePrincipal the mount of vQuote charged was sent to UniswapV3Pool\n event Mint(int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 vTokenPrincipal, uint256 vQuotePrincipal);\n\n /// @notice Emitted whenever liquidity is removed\n /// @param tickLower the lower tick of the range\n /// @param tickUpper the upper tick of the range\n /// @param liquidity the amount of liquidity that was removed\n /// @param vTokenPrincipal the amount of vToken that was received from UniswapV3Pool\n /// @param vQuotePrincipal the mount of vQuote charged was received from UniswapV3Pool\n event Burn(int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 vTokenPrincipal, uint256 vQuotePrincipal);\n\n /// @notice Emitted whenever clearing house enquired about the accrued protocol fees\n /// @param amount the amount of accrued protocol fees\n event AccruedProtocolFeeCollected(uint256 amount);\n\n /// @notice Emitted when governance updates the liquidity fees\n /// @param liquidityFeePips the new liquidity fee ratio\n event LiquidityFeeUpdated(uint24 liquidityFeePips);\n\n /// @notice Emitted when governance updates the protocol fees\n /// @param protocolFeePips the new protocol fee ratio\n event ProtocolFeeUpdated(uint24 protocolFeePips);\n\n /// @notice Emitted when funding rate override is updated\n /// @param fundingRateOverrideX128 the new funding rate override value\n event FundingRateOverrideUpdated(int256 fundingRateOverrideX128);\n\n function initialize(InitializeVPoolWrapperParams memory params) external;\n\n function vPool() external view returns (IUniswapV3Pool);\n\n function getValuesInside(int24 tickLower, int24 tickUpper)\n external\n view\n returns (WrapperValuesInside memory wrapperValuesInside);\n\n function getExtrapolatedValuesInside(int24 tickLower, int24 tickUpper)\n external\n view\n returns (WrapperValuesInside memory wrapperValuesInside);\n\n function swap(\n bool swapVTokenForVQuote, // zeroForOne\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96\n ) external returns (SwapResult memory swapResult);\n\n function mint(\n int24 tickLower,\n int24 tickUpper,\n uint128 liquidity\n )\n external\n returns (\n uint256 vTokenPrincipal,\n uint256 vQuotePrincipal,\n WrapperValuesInside memory wrapperValuesInside\n );\n\n function burn(\n int24 tickLower,\n int24 tickUpper,\n uint128 liquidity\n )\n external\n returns (\n uint256 vTokenPrincipal,\n uint256 vQuotePrincipal,\n WrapperValuesInside memory wrapperValuesInside\n );\n\n function getSumAX128() external view returns (int256);\n\n function getExtrapolatedSumAX128() external view returns (int256);\n\n function liquidityFeePips() external view returns (uint24);\n\n function protocolFeePips() external view returns (uint24);\n\n /// @notice Used by clearing house to update funding rate when clearing house is paused or unpaused.\n /// @param useZeroFundingRate: used to discount funding payment during the duration ch was paused.\n function updateGlobalFundingState(bool useZeroFundingRate) external;\n\n /// @notice Used by clearing house to know how much protocol fee was collected.\n /// @return accruedProtocolFeeLast amount of protocol fees accrued since last collection.\n /// @dev Does not do any token transfer, just reduces the state in wrapper by accruedProtocolFeeLast.\n /// Clearing house already has the amount of settlement tokens to send to treasury.\n function collectAccruedProtocolFee() external returns (uint256 accruedProtocolFeeLast);\n}\n" + }, + "contracts/interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\ninterface IVToken is IERC20 {\n function mint(address account, uint256 amount) external;\n\n function burn(uint256 amount) external;\n\n function setVPoolWrapper(address) external;\n}\n" + }, + "contracts/libraries/Uint48.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\n/// @title Uint48 concating functions\nlibrary Uint48Lib {\n /// @notice Packs two int24 values into uint48\n /// @dev Used for concating two ticks into 48 bits value\n /// @param val1 First 24 bits value\n /// @param val2 Second 24 bits value\n /// @return concatenated value\n function concat(int24 val1, int24 val2) internal pure returns (uint48 concatenated) {\n assembly {\n concatenated := add(shl(24, val1), and(val2, 0x000000ffffff))\n }\n }\n\n /// @notice Unpacks uint48 into two int24 values\n /// @dev Used for unpacking 48 bits value into two 24 bits values\n /// @param concatenated 48 bits value\n /// @return val1 First 24 bits value\n /// @return val2 Second 24 bits value\n function unconcat(uint48 concatenated) internal pure returns (int24 val1, int24 val2) {\n assembly {\n val2 := concatenated\n val1 := shr(24, concatenated)\n }\n }\n}\n" + }, + "contracts/libraries/WordHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\n\nimport { Uint48Lib } from '../libraries/Uint48.sol';\n\nlibrary WordHelper {\n using WordHelper for bytes32;\n\n struct Word {\n bytes32 data;\n }\n\n // struct Word methods\n\n function copyToMemory(bytes32 data) internal pure returns (Word memory) {\n return Word(data);\n }\n\n function pop(Word memory input, uint256 bits) internal pure returns (uint256 value) {\n (value, input.data) = pop(input.data, bits);\n }\n\n function popAddress(Word memory input) internal pure returns (address value) {\n (value, input.data) = popAddress(input.data);\n }\n\n function popUint8(Word memory input) internal pure returns (uint8 value) {\n (value, input.data) = popUint8(input.data);\n }\n\n function popUint16(Word memory input) internal pure returns (uint16 value) {\n (value, input.data) = popUint16(input.data);\n }\n\n function popUint32(Word memory input) internal pure returns (uint32 value) {\n (value, input.data) = popUint32(input.data);\n }\n\n function popUint64(Word memory input) internal pure returns (uint64 value) {\n (value, input.data) = popUint64(input.data);\n }\n\n function popUint128(Word memory input) internal pure returns (uint128 value) {\n (value, input.data) = popUint128(input.data);\n }\n\n function popBool(Word memory input) internal pure returns (bool value) {\n (value, input.data) = popBool(input.data);\n }\n\n function slice(\n Word memory input,\n uint256 start,\n uint256 end\n ) internal pure returns (bytes32 val) {\n return slice(input.data, start, end);\n }\n\n // primitive uint256 methods\n\n function fromUint(uint256 input) internal pure returns (bytes32 output) {\n assembly {\n output := input\n }\n }\n\n // primitive bytes32 methods\n\n function keccak256One(bytes32 input) internal pure returns (bytes32 result) {\n assembly {\n mstore(0, input)\n result := keccak256(0, 0x20)\n }\n }\n\n function keccak256Two(bytes32 paddedKey, bytes32 mappingSlot) internal pure returns (bytes32 result) {\n assembly {\n mstore(0, paddedKey)\n mstore(0x20, mappingSlot)\n result := keccak256(0, 0x40)\n }\n }\n\n function offset(bytes32 key, uint256 offset_) internal pure returns (bytes32) {\n assembly {\n key := add(key, offset_)\n }\n return key;\n }\n\n function slice(\n bytes32 input,\n uint256 start,\n uint256 end\n ) internal pure returns (bytes32 val) {\n assembly {\n val := shl(start, input)\n val := shr(add(start, sub(256, end)), val)\n }\n }\n\n /// @notice pops bits from the right side of the input\n /// @dev E.g. input = 0x0102030405060708091011121314151617181920212223242526272829303132\n /// input.pop(16) -> 0x3132\n /// input.pop(16) -> 0x2930\n /// input -> 0x0000000001020304050607080910111213141516171819202122232425262728\n /// @dev this does not throw on underflow, value returned would be zero\n /// @param input the input bytes\n /// @param bits the number of bits to pop\n /// @return value of the popped bits\n /// @return inputUpdated the input bytes shifted right by bits\n function pop(bytes32 input, uint256 bits) internal pure returns (uint256 value, bytes32 inputUpdated) {\n assembly {\n let shift := sub(256, bits)\n value := shr(shift, shl(shift, input))\n inputUpdated := shr(bits, input)\n }\n }\n\n function popAddress(bytes32 input) internal pure returns (address value, bytes32 inputUpdated) {\n uint256 temp;\n (temp, inputUpdated) = pop(input, 160);\n assembly {\n value := temp\n }\n }\n\n function popUint8(bytes32 input) internal pure returns (uint8 value, bytes32 inputUpdated) {\n uint256 temp;\n (temp, inputUpdated) = pop(input, 8);\n value = uint8(temp);\n }\n\n function popUint16(bytes32 input) internal pure returns (uint16 value, bytes32 inputUpdated) {\n uint256 temp;\n (temp, inputUpdated) = pop(input, 16);\n value = uint16(temp);\n }\n\n function popUint32(bytes32 input) internal pure returns (uint32 value, bytes32 inputUpdated) {\n uint256 temp;\n (temp, inputUpdated) = pop(input, 32);\n value = uint32(temp);\n }\n\n function popUint64(bytes32 input) internal pure returns (uint64 value, bytes32 inputUpdated) {\n uint256 temp;\n (temp, inputUpdated) = pop(input, 64);\n value = uint64(temp);\n }\n\n function popUint128(bytes32 input) internal pure returns (uint128 value, bytes32 inputUpdated) {\n uint256 temp;\n (temp, inputUpdated) = pop(input, 128);\n value = uint128(temp);\n }\n\n function popBool(bytes32 input) internal pure returns (bool value, bytes32 inputUpdated) {\n uint256 temp;\n (temp, inputUpdated) = pop(input, 8);\n value = temp != 0;\n }\n\n function toAddress(bytes32 input) internal pure returns (address value) {\n return address(toUint160(input));\n }\n\n function toUint8(bytes32 input) internal pure returns (uint8 value) {\n return uint8(toUint256(input));\n }\n\n function toUint16(bytes32 input) internal pure returns (uint16 value) {\n return uint16(toUint256(input));\n }\n\n function toUint32(bytes32 input) internal pure returns (uint32 value) {\n return uint32(toUint256(input));\n }\n\n function toUint48(bytes32 input) internal pure returns (uint48 value) {\n return uint48(toUint256(input));\n }\n\n function toUint64(bytes32 input) internal pure returns (uint64 value) {\n return uint64(toUint256(input));\n }\n\n function toUint128(bytes32 input) internal pure returns (uint128 value) {\n return uint128(toUint256(input));\n }\n\n function toUint160(bytes32 input) internal pure returns (uint160 value) {\n return uint160(toUint256(input));\n }\n\n function toUint256(bytes32 input) internal pure returns (uint256 value) {\n assembly {\n value := input\n }\n }\n\n function toInt256(bytes32 input) internal pure returns (int256 value) {\n assembly {\n value := input\n }\n }\n\n function toBool(bytes32 input) internal pure returns (bool value) {\n (value, ) = popBool(input);\n }\n\n bytes32 constant ZERO = bytes32(uint256(0));\n\n function convertToUint32Array(bytes32 active) internal pure returns (uint32[] memory activeArr) {\n unchecked {\n uint256 i = 8;\n while (i > 0) {\n bytes32 id = active.slice((i - 1) * 32, i * 32);\n if (id == ZERO) {\n break;\n }\n i--;\n }\n activeArr = new uint32[](8 - i);\n while (i < 8) {\n activeArr[7 - i] = active.slice(i * 32, (i + 1) * 32).toUint32();\n i++;\n }\n }\n }\n\n function convertToTickRangeArray(bytes32 active)\n internal\n pure\n returns (IClearingHouseStructures.TickRange[] memory activeArr)\n {\n unchecked {\n uint256 i = 5;\n while (i > 0) {\n bytes32 id = active.slice((i - 1) * 48, i * 48);\n if (id == ZERO) {\n break;\n }\n i--;\n }\n activeArr = new IClearingHouseStructures.TickRange[](5 - i);\n while (i < 5) {\n // 256 - 48 * 5 = 16\n (int24 tickLower, int24 tickUpper) = Uint48Lib.unconcat(\n active.slice(16 + i * 48, 16 + (i + 1) * 48).toUint48()\n );\n activeArr[4 - i].tickLower = tickLower;\n activeArr[4 - i].tickUpper = tickUpper;\n i++;\n }\n }\n }\n}\n" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "@uniswap/v3-core-0.8-support/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 /// @return 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 /// @return observationIndex The index of the last oracle observation that was written,\n /// @return observationCardinality The current maximum number of observations stored in the pool,\n /// @return observationCardinalityNext The next maximum number of observations, to be updated when the observation.\n /// @return 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 /// @return The liquidity at the current price of the pool\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 /// @return liquidityNet how much liquidity changes when the pool price crosses the tick,\n /// @return feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\n /// @return feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\n /// @return tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\n /// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\n /// @return secondsOutside the seconds spent on the other side of the tick from the current tick,\n /// @return 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 /// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\n /// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\n /// @return tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\n /// @return 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 /// @return tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\n /// @return secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\n /// @return 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" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "@uniswap/v3-core-0.8-support/contracts/interfaces/pool/IUniswapV3PoolErrors.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Errors emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolErrors {\n error LOK();\n error TLU();\n error TLM();\n error TUM();\n error AI();\n error M0();\n error M1();\n error AS();\n error IIA();\n error L();\n error F0();\n error F1();\n}\n" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "contracts/interfaces/IGovernable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface IGovernable {\n function governance() external view returns (address);\n\n function governancePending() external view returns (address);\n\n function teamMultisig() external view returns (address);\n\n function teamMultisigPending() external view returns (address);\n\n function initiateGovernanceTransfer(address newGovernancePending) external;\n\n function acceptGovernanceTransfer() external;\n\n function initiateTeamMultisigTransfer(address newTeamMultisigPending) external;\n\n function acceptTeamMultisigTransfer() external;\n}\n" + }, + "contracts/interfaces/clearinghouse/IClearingHouseActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.0;\n\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\n\ninterface IClearingHouseActions is IClearingHouseStructures {\n /// @notice creates a new account and adds it to the accounts map\n /// @return newAccountId - serial number of the new account created\n function createAccount() external returns (uint256 newAccountId);\n\n /// @notice deposits 'amount' of token associated with 'poolId'\n /// @param accountId account id\n /// @param collateralId truncated address of token to deposit\n /// @param amount amount of token to deposit\n function updateMargin(\n uint256 accountId,\n uint32 collateralId,\n int256 amount\n ) external;\n\n /// @notice creates a new account and deposits 'amount' of token associated with 'poolId'\n /// @param collateralId truncated address of collateral token to deposit\n /// @param amount amount of token to deposit\n /// @return newAccountId - serial number of the new account created\n function createAccountAndAddMargin(uint32 collateralId, uint256 amount) external returns (uint256 newAccountId);\n\n /// @notice withdraws 'amount' of settlement token from the profit made\n /// @param accountId account id\n /// @param amount amount of token to withdraw\n function updateProfit(uint256 accountId, int256 amount) external;\n\n /// @notice settles the profit/loss made with the settlement token collateral deposits\n /// @param accountId account id\n function settleProfit(uint256 accountId) external;\n\n /// @notice swaps token associated with 'poolId' by 'amount' (Long if amount>0 else Short)\n /// @param accountId account id\n /// @param poolId truncated address of token to withdraw\n /// @param swapParams swap parameters\n function swapToken(\n uint256 accountId,\n uint32 poolId,\n SwapParams memory swapParams\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut);\n\n /// @notice updates range order of token associated with 'poolId' by 'liquidityDelta' (Adds if amount>0 else Removes)\n /// @notice also can be used to update limitOrderType\n /// @param accountId account id\n /// @param poolId truncated address of token to withdraw\n /// @param liquidityChangeParams liquidity change parameters\n function updateRangeOrder(\n uint256 accountId,\n uint32 poolId,\n LiquidityChangeParams calldata liquidityChangeParams\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut);\n\n /// @notice keeper call to remove a limit order\n /// @dev checks the position of current price relative to limit order and checks limitOrderType\n /// @param accountId account id\n /// @param poolId truncated address of token to withdraw\n /// @param tickLower liquidity change parameters\n /// @param tickUpper liquidity change parameters\n function removeLimitOrder(\n uint256 accountId,\n uint32 poolId,\n int24 tickLower,\n int24 tickUpper\n ) external;\n\n /// @notice keeper call for liquidation of range position\n /// @dev removes all the active range positions and gives liquidator a percent of notional amount closed + fixedFee\n /// @param accountId account id\n function liquidateLiquidityPositions(uint256 accountId) external;\n\n /// @notice keeper call for liquidation of token position\n /// @dev transfers the fraction of token position at a discount to current price to liquidators account and gives liquidator some fixedFee\n /// @param targetAccountId account id\n /// @param poolId truncated address of token to withdraw\n /// @return keeperFee - amount of fees transferred to keeper\n function liquidateTokenPosition(uint256 targetAccountId, uint32 poolId) external returns (int256 keeperFee);\n}\n" + }, + "contracts/interfaces/clearinghouse/IClearingHouseCustomErrors.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { IVToken } from '../IVToken.sol';\n\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\n\ninterface IClearingHouseCustomErrors is IClearingHouseStructures {\n /// @notice error to denote invalid account access\n /// @param senderAddress address of msg sender\n error AccessDenied(address senderAddress);\n\n /// @notice error to denote usage of uninitialized token\n /// @param collateralId address of token\n error CollateralDoesNotExist(uint32 collateralId);\n\n /// @notice error to denote usage of unsupported collateral token\n /// @param collateralId address of token\n error CollateralNotAllowedForUse(uint32 collateralId);\n\n /// @notice error to denote unpause is in progress, hence cannot pause\n error CannotPauseIfUnpauseInProgress();\n\n /// @notice error to denote pause is in progress, hence cannot unpause\n error CannotUnpauseIfPauseInProgress();\n\n /// @notice error to denote incorrect address is supplied while updating collateral settings\n /// @param incorrectAddress incorrect address of collateral token\n /// @param correctAddress correct address of collateral token\n error IncorrectCollateralAddress(IERC20 incorrectAddress, IERC20 correctAddress);\n\n /// @notice error to denote invalid address supplied as a collateral token\n /// @param invalidAddress invalid address of collateral token\n error InvalidCollateralAddress(address invalidAddress);\n\n /// @notice error to denote invalid token liquidation (fraction to liquidate> 1)\n error InvalidTokenLiquidationParameters();\n\n /// @notice this is errored when the enum (uint8) value is out of bounds\n /// @param multicallOperationType is the value that is out of bounds\n error InvalidMulticallOperationType(MulticallOperationType multicallOperationType);\n\n /// @notice error to denote that keeper fee is negative or zero\n error KeeperFeeNotPositive(int256 keeperFee);\n\n /// @notice error to denote low notional value of txn\n /// @param notionalValue notional value of txn\n error LowNotionalValue(uint256 notionalValue);\n\n /// @notice error to denote that caller is not ragetrade factory\n error NotRageTradeFactory();\n\n /// @notice error to denote usage of uninitialized pool\n /// @param poolId unitialized truncated address supplied\n error PoolDoesNotExist(uint32 poolId);\n\n /// @notice error to denote usage of unsupported pool\n /// @param poolId address of token\n error PoolNotAllowedForTrade(uint32 poolId);\n\n /// @notice error to denote slippage of txn beyond set threshold\n error SlippageBeyondTolerance();\n\n /// @notice error to denote that zero amount is passed and it's prohibited\n error ZeroAmount();\n\n /// @notice error to denote an invalid setting for parameters\n error InvalidSetting(uint256 errorCode);\n}\n" + }, + "contracts/interfaces/clearinghouse/IClearingHouseEnums.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IClearingHouseEnums {\n enum LimitOrderType {\n NONE,\n LOWER_LIMIT,\n UPPER_LIMIT\n }\n\n enum MulticallOperationType {\n UPDATE_MARGIN,\n UPDATE_PROFIT,\n SWAP_TOKEN,\n UPDATE_RANGE_ORDER,\n REMOVE_LIMIT_ORDER,\n LIQUIDATE_LIQUIDITY_POSITIONS,\n LIQUIDATE_TOKEN_POSITION\n }\n}\n" + }, + "contracts/interfaces/clearinghouse/IClearingHouseEvents.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { IVToken } from '../IVToken.sol';\n\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\n\ninterface IClearingHouseEvents is IClearingHouseStructures {\n /// @notice denotes new account creation\n /// @param ownerAddress wallet address of account owner\n /// @param accountId serial number of the account\n event AccountCreated(address indexed ownerAddress, uint256 accountId);\n\n /// @notice new collateral supported as margin\n /// @param cTokenInfo collateral token info\n event CollateralSettingsUpdated(IERC20 cToken, CollateralSettings cTokenInfo);\n\n /// @notice maintainance margin ratio of a pool changed\n /// @param poolId id of the rage trade pool\n /// @param settings new settings\n event PoolSettingsUpdated(uint32 poolId, PoolSettings settings);\n\n /// @notice protocol settings changed\n /// @param liquidationParams liquidation params\n /// @param removeLimitOrderFee fee for remove limit order\n /// @param minimumOrderNotional minimum order notional\n /// @param minRequiredMargin minimum required margin\n event ProtocolSettingsUpdated(\n LiquidationParams liquidationParams,\n uint256 removeLimitOrderFee,\n uint256 minimumOrderNotional,\n uint256 minRequiredMargin\n );\n\n event PausedUpdated(bool paused);\n}\n" + }, + "contracts/interfaces/clearinghouse/IClearingHouseOwnerActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { IVToken } from '../IVToken.sol';\n\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\n\ninterface IClearingHouseOwnerActions is IClearingHouseStructures {\n /// @notice updates the collataral settings\n /// @param cToken collateral token\n /// @param collateralSettings settings\n function updateCollateralSettings(IERC20 cToken, CollateralSettings memory collateralSettings) external;\n\n /// @notice updates the rage trade pool settings\n /// @param poolId rage trade pool id\n /// @param newSettings updated rage trade pool settings\n function updatePoolSettings(uint32 poolId, PoolSettings calldata newSettings) external;\n\n /// @notice updates the protocol settings\n /// @param liquidationParams liquidation params\n /// @param removeLimitOrderFee fee for remove limit order\n /// @param minimumOrderNotional minimum order notional\n /// @param minRequiredMargin minimum required margin\n function updateProtocolSettings(\n LiquidationParams calldata liquidationParams,\n uint256 removeLimitOrderFee,\n uint256 minimumOrderNotional,\n uint256 minRequiredMargin\n ) external;\n\n /// @notice withdraws protocol fees collected in the supplied wrappers to team multisig\n /// @param numberOfPoolsToUpdateInThisTx number of pools to collect fees from\n function withdrawProtocolFee(uint256 numberOfPoolsToUpdateInThisTx) external;\n}\n" + }, + "contracts/interfaces/clearinghouse/IClearingHouseStructures.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { IOracle } from '../IOracle.sol';\nimport { IVToken } from '../IVToken.sol';\nimport { IVPoolWrapper } from '../IVPoolWrapper.sol';\n\nimport { IClearingHouseEnums } from './IClearingHouseEnums.sol';\n\ninterface IClearingHouseStructures is IClearingHouseEnums {\n struct BalanceAdjustments {\n int256 vQuoteIncrease; // specifies the increase in vQuote balance\n int256 vTokenIncrease; // specifies the increase in token balance\n int256 traderPositionIncrease; // specifies the increase in trader position\n }\n\n struct Collateral {\n IERC20 token; // address of the collateral token\n CollateralSettings settings; // collateral settings, changable by governance later\n }\n\n struct CollateralSettings {\n IOracle oracle; // address of oracle which gives price to be used for collateral\n uint32 twapDuration; // duration of the twap in seconds\n bool isAllowedForDeposit; // whether the collateral is allowed to be deposited at the moment\n }\n\n struct CollateralDepositView {\n IERC20 collateral; // address of the collateral token\n uint256 balance; // balance of the collateral in the account\n }\n\n struct LiquidityChangeParams {\n int24 tickLower; // tick lower of the range\n int24 tickUpper; // tick upper of the range\n int128 liquidityDelta; // positive to add liquidity, negative to remove liquidity\n uint160 sqrtPriceCurrent; // hint for virtual price, to prevent sandwitch attack\n uint16 slippageToleranceBps; // slippage tolerance in bps, to prevent sandwitch attack\n bool closeTokenPosition; // whether to close the token position generated due to the liquidity change\n LimitOrderType limitOrderType; // limit order type\n bool settleProfit; // whether to settle profit against USDC margin\n }\n\n struct LiquidityPositionView {\n int24 tickLower; // tick lower of the range\n int24 tickUpper; // tick upper of the range\n uint128 liquidity; // liquidity in the range by the account\n int256 vTokenAmountIn; // amount of token supplied by the account, to calculate net position\n int256 sumALastX128; // checkpoint of the term A in funding payment math\n int256 sumBInsideLastX128; // checkpoint of the term B in funding payment math\n int256 sumFpInsideLastX128; // checkpoint of the term Fp in funding payment math\n uint256 sumFeeInsideLastX128; // checkpoint of the trading fees\n LimitOrderType limitOrderType; // limit order type\n }\n\n struct LiquidationParams {\n uint16 rangeLiquidationFeeFraction; // fraction of net token position rm from the range to be charged as liquidation fees (in 1e5)\n uint16 tokenLiquidationFeeFraction; // fraction of traded amount of vquote to be charged as liquidation fees (in 1e5)\n uint16 closeFactorMMThresholdBps; // fraction the MM threshold for partial liquidation (in 1e4)\n uint16 partialLiquidationCloseFactorBps; // fraction the % of position to be liquidated if partial liquidation should occur (in 1e4)\n uint16 insuranceFundFeeShareBps; // fraction of the fee share for insurance fund out of the total liquidation fee (in 1e4)\n uint16 liquidationSlippageSqrtToleranceBps; // fraction of the max sqrt price slippage threshold (in 1e4) (can be set to - actual price slippage tolerance / 2)\n uint64 maxRangeLiquidationFees; // maximum range liquidation fees (in settlement token amount decimals)\n uint64 minNotionalLiquidatable; // minimum notional value of position for it to be eligible for partial liquidation (in settlement token amount decimals)\n }\n\n struct MulticallOperation {\n MulticallOperationType operationType; // operation type\n bytes data; // abi encoded data for the operation\n }\n\n struct Pool {\n IVToken vToken; // address of the vToken, poolId = vToken.truncate()\n IUniswapV3Pool vPool; // address of the UniswapV3Pool(token0=vToken, token1=vQuote, fee=500)\n IVPoolWrapper vPoolWrapper; // wrapper address\n PoolSettings settings; // pool settings, which can be updated by governance later\n }\n\n struct PoolSettings {\n uint16 initialMarginRatioBps; // margin ratio (1e4) considered for create/update position, removing margin or profit\n uint16 maintainanceMarginRatioBps; // margin ratio (1e4) considered for liquidations by keeper\n uint16 maxVirtualPriceDeviationRatioBps; // maximum deviation (1e4) from the current virtual price\n uint32 twapDuration; // twap duration (seconds) for oracle\n bool isAllowedForTrade; // whether the pool is allowed to be traded at the moment\n bool isCrossMargined; // whether cross margined is done for positions of this pool\n IOracle oracle; // spot price feed twap oracle for this pool\n }\n\n struct SwapParams {\n int256 amount; // amount of tokens/vQuote to swap\n uint160 sqrtPriceLimit; // threshold sqrt price which should not be crossed\n bool isNotional; // whether the amount represents vQuote amount\n bool isPartialAllowed; // whether to end swap (partial) when sqrtPriceLimit is reached, instead of reverting\n bool settleProfit; // whether to settle profit against USDC margin\n }\n\n struct TickRange {\n int24 tickLower;\n int24 tickUpper;\n }\n\n struct VTokenPositionView {\n uint32 poolId; // id of the pool of which this token position is for\n int256 balance; // vTokenLong - vTokenShort\n int256 netTraderPosition; // net position due to trades and liquidity change carries\n int256 sumALastX128; // checkoint of the term A in funding payment math\n LiquidityPositionView[] liquidityPositions; // liquidity positions of the account in the pool\n }\n}\n" + }, + "contracts/interfaces/clearinghouse/IClearingHouseSystemActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { IInsuranceFund } from '../IInsuranceFund.sol';\nimport { IOracle } from '../IOracle.sol';\nimport { IVQuote } from '../IVQuote.sol';\nimport { IVToken } from '../IVToken.sol';\n\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\n\ninterface IClearingHouseSystemActions is IClearingHouseStructures {\n /// @notice initializes clearing house contract\n /// @param rageTradeFactoryAddress rage trade factory address\n /// @param defaultCollateralToken address of default collateral token\n /// @param defaultCollateralTokenOracle address of default collateral token oracle\n /// @param insuranceFund address of insurance fund\n /// @param vQuote address of vQuote\n function initialize(\n address rageTradeFactoryAddress,\n address initialGovernance,\n address initialTeamMultisig,\n IERC20 defaultCollateralToken,\n IOracle defaultCollateralTokenOracle,\n IInsuranceFund insuranceFund,\n IVQuote vQuote\n ) external;\n\n function registerPool(Pool calldata poolInfo) external;\n}\n" + }, + "contracts/interfaces/clearinghouse/IClearingHouseView.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.0;\n\nimport { IClearingHouseStructures } from './IClearingHouseStructures.sol';\nimport { IExtsload } from '../IExtsload.sol';\n\ninterface IClearingHouseView is IClearingHouseStructures, IExtsload {\n /// @notice Gets the market value and required margin of an account\n /// @dev This method can be used to check if an account is under water or not.\n /// If accountMarketValue < requiredMargin then liquidation can take place.\n /// @param accountId the account id\n /// @param isInitialMargin true is initial margin, false is maintainance margin\n /// @return accountMarketValue the market value of the account, due to collateral and positions\n /// @return requiredMargin margin needed due to positions\n function getAccountMarketValueAndRequiredMargin(uint256 accountId, bool isInitialMargin)\n external\n view\n returns (int256 accountMarketValue, int256 requiredMargin);\n\n /// @notice Gets the net profit of an account\n /// @param accountId the account id\n /// @return accountNetProfit the net profit of the account\n function getAccountNetProfit(uint256 accountId) external view returns (int256 accountNetProfit);\n\n /// @notice Gets the net position of an account\n /// @param accountId the account id\n /// @param poolId the id of the pool (vETH, ... etc)\n /// @return netPosition the net position of the account\n function getAccountNetTokenPosition(uint256 accountId, uint32 poolId) external view returns (int256 netPosition);\n\n /// @notice Gets the real twap price from the respective oracle of the given poolId\n /// @param poolId the id of the pool\n /// @return realPriceX128 the real price of the pool\n function getRealTwapPriceX128(uint32 poolId) external view returns (uint256 realPriceX128);\n\n /// @notice Gets the virtual twap price from the respective oracle of the given poolId\n /// @param poolId the id of the pool\n /// @return virtualPriceX128 the virtual price of the pool\n function getVirtualTwapPriceX128(uint32 poolId) external view returns (uint256 virtualPriceX128);\n}\n" + }, + "contracts/interfaces/IInsuranceFund.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\ninterface IInsuranceFund {\n function initialize(\n IERC20 settlementToken,\n address clearingHouse,\n string calldata name,\n string calldata symbol\n ) external;\n\n function claim(uint256 amount) external;\n}\n" + }, + "contracts/test/ClearingHouseExtsloadTest.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { IClearingHouse } from '../interfaces/IClearingHouse.sol';\nimport { IExtsload } from '../interfaces/IExtsload.sol';\nimport { IOracle } from '../interfaces/IOracle.sol';\nimport { IVQuote } from '../interfaces/IVQuote.sol';\n\nimport { ClearingHouseExtsload } from '../extsloads/ClearingHouseExtsload.sol';\n\ncontract ClearingHouseExtsloadTest {\n modifier notView() {\n assembly {\n if iszero(1) {\n sstore(0, 0)\n }\n }\n _;\n }\n\n function getVPoolAndTwapDuration(IClearingHouse clearingHouse, uint32 poolId)\n public\n view\n returns (IUniswapV3Pool vPool, uint32 twapDuration)\n {\n (vPool, twapDuration) = ClearingHouseExtsload.getVPoolAndTwapDuration(clearingHouse, poolId);\n }\n\n function checkVPoolAndTwapDuration(IClearingHouse clearingHouse, uint32 poolId)\n public\n notView\n returns (IUniswapV3Pool vPool, uint32 twapDuration)\n {\n (vPool, twapDuration) = ClearingHouseExtsload.getVPoolAndTwapDuration(clearingHouse, poolId);\n }\n\n function getVPool(IClearingHouse clearingHouse, uint32 poolId) public view returns (IUniswapV3Pool vPool) {\n vPool = ClearingHouseExtsload.getVPool(clearingHouse, poolId);\n }\n\n function getPoolSettings(IClearingHouse clearingHouse, uint32 poolId)\n public\n view\n returns (IClearingHouse.PoolSettings memory settings)\n {\n return ClearingHouseExtsload.getPoolSettings(clearingHouse, poolId);\n }\n\n function isPoolIdAvailable(IClearingHouse clearingHouse, uint32 poolId) public view returns (bool) {\n return ClearingHouseExtsload.isPoolIdAvailable(clearingHouse, poolId);\n }\n\n function getPoolInfo(IClearingHouse clearingHouse, uint32 poolId) public view returns (IClearingHouse.Pool memory) {\n return ClearingHouseExtsload.getPoolInfo(clearingHouse, poolId);\n }\n\n function getProtocolInfo(IClearingHouse clearingHouse)\n external\n view\n returns (\n IERC20 settlementToken,\n IVQuote vQuote,\n IClearingHouse.LiquidationParams memory liquidationParams,\n uint256 minRequiredMargin,\n uint256 removeLimitOrderFee,\n uint256 minimumOrderNotional\n )\n {\n return ClearingHouseExtsload.getProtocolInfo(clearingHouse);\n }\n\n function getCollateralInfo(IClearingHouse clearingHouse, uint32 collateralId)\n external\n view\n returns (IClearingHouse.Collateral memory)\n {\n return ClearingHouseExtsload.getCollateralInfo(clearingHouse, collateralId);\n }\n\n function getAccountInfo(IClearingHouse clearingHouse, uint256 accountId)\n external\n view\n returns (\n address owner,\n int256 vQuoteBalance,\n uint32[] memory activeCollateralIds,\n uint32[] memory activePoolIds\n )\n {\n return ClearingHouseExtsload.getAccountInfo(clearingHouse, accountId);\n }\n\n function getAccountCollateralInfo(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 collateralId\n ) external view returns (IERC20 collateral, uint256 balance) {\n return ClearingHouseExtsload.getAccountCollateralInfo(clearingHouse, accountId, collateralId);\n }\n\n function getAccountCollateralBalance(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 collateralId\n ) external view returns (uint256 balance) {\n return ClearingHouseExtsload.getAccountCollateralBalance(clearingHouse, accountId, collateralId);\n }\n\n function getAccountTokenPositionInfo(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 poolId\n )\n external\n view\n returns (\n int256 balance,\n int256 netTraderPosition,\n int256 sumALastX128\n )\n {\n return ClearingHouseExtsload.getAccountTokenPositionInfo(clearingHouse, accountId, poolId);\n }\n\n function getAccountPositionInfo(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 poolId\n )\n external\n view\n returns (\n int256 balance,\n int256 netTraderPosition,\n int256 sumALastX128,\n IClearingHouse.TickRange[] memory activeTickRanges\n )\n {\n return ClearingHouseExtsload.getAccountPositionInfo(clearingHouse, accountId, poolId);\n }\n\n function getAccountLiquidityPositionList(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 poolId\n ) external view returns (IClearingHouse.TickRange[] memory activeTickRanges) {\n return ClearingHouseExtsload.getAccountLiquidityPositionList(clearingHouse, accountId, poolId);\n }\n\n function getAccountLiquidityPositionInfo(\n IClearingHouse clearingHouse,\n uint256 accountId,\n uint32 poolId,\n int24 tickLower,\n int24 tickUpper\n )\n external\n view\n returns (\n uint8 limitOrderType,\n uint128 liquidity,\n int256 vTokenAmountIn,\n int256 sumALastX128,\n int256 sumBInsideLastX128,\n int256 sumFpInsideLastX128,\n uint256 sumFeeInsideLastX128\n )\n {\n return\n ClearingHouseExtsload.getAccountLiquidityPositionInfo(\n clearingHouse,\n accountId,\n poolId,\n tickLower,\n tickUpper\n );\n }\n\n function getProtocolSlot() external pure returns (bytes32) {\n return ClearingHouseExtsload._getProtocolSlot();\n }\n\n function getProtocolOffsets()\n external\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return ClearingHouseExtsload._getProtocolOffsets();\n }\n\n function getPoolOffsets()\n external\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return ClearingHouseExtsload._getPoolOffsets();\n }\n\n function getCollateralOffsets() external pure returns (uint256, uint256) {\n return ClearingHouseExtsload._getCollateralOffsets();\n }\n\n function getAccountsMappingSlot() external pure returns (bytes32) {\n return ClearingHouseExtsload._getAccountsMappingSlot();\n }\n\n function getAccountOffsets()\n external\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return ClearingHouseExtsload._getAccountOffsets();\n }\n\n function getVTokenPositionOffsets()\n external\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return ClearingHouseExtsload._getVTokenPositionOffsets();\n }\n\n function getLiquidityPositionOffsets()\n external\n pure\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n {\n return ClearingHouseExtsload._getLiquidityPositionOffsets();\n }\n}\n" + }, + "contracts/test/mocks/VPoolWrapperMockRealistic.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\nimport { IUniswapV3PoolDeployer } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3PoolDeployer.sol';\nimport { IUniswapV3MintCallback } from '@uniswap/v3-core-0.8-support/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\nimport { IUniswapV3SwapCallback } from '@uniswap/v3-core-0.8-support/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\n\nimport { IVPoolWrapper } from '../../interfaces/IVPoolWrapper.sol';\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\nimport { IVToken } from '../../interfaces/IVToken.sol';\nimport { IOracle } from '../../interfaces/IOracle.sol';\nimport { IVToken } from '../../interfaces/IVToken.sol';\n\nimport { FundingPayment } from '../../libraries/FundingPayment.sol';\nimport { SimulateSwap } from '../../libraries/SimulateSwap.sol';\nimport { PriceMath } from '../../libraries/PriceMath.sol';\nimport { SignedMath } from '../../libraries/SignedMath.sol';\nimport { SignedFullMath } from '../../libraries/SignedFullMath.sol';\nimport { UniswapV3PoolHelper } from '../../libraries/UniswapV3PoolHelper.sol';\n\nimport { VPoolWrapper } from '../../protocol/wrapper/VPoolWrapper.sol';\n\ncontract VPoolWrapperMockRealistic is VPoolWrapper {\n uint48 public blockTimestamp;\n\n constructor() VPoolWrapper() {\n fpGlobal.timestampLast = 0;\n }\n\n function setFpGlobalLastTimestamp(uint48 timestamp) external {\n fpGlobal.timestampLast = timestamp;\n }\n\n function setBlockTimestamp(uint48 timestamp) external {\n blockTimestamp = timestamp;\n }\n\n function _blockTimestamp() internal view virtual override returns (uint48) {\n return blockTimestamp;\n }\n}\n" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.4.0;\n\n/// @title FixedPoint128\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\nlibrary FixedPoint128 {\n uint256 internal constant Q128 = 0x100000000000000000000000000000000;\n}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.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×b÷denominator) 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 unchecked {\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 = (0 - 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\n /// @notice Calculates ceil(a×b÷denominator) 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 unchecked {\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}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.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 error T();\n error R();\n\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 unchecked {\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\n if (absTick > uint256(int256(MAX_TICK))) revert T();\n\n uint256 ratio = absTick & 0x1 != 0\n ? 0xfffcb933bd6fad37aa2d162d1a594001\n : 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\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 unchecked {\n // second inequality must be < because the price can never reach the price at the max tick\n if (!(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO)) revert 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}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3PoolDeployer.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title An interface for a contract that is capable of deploying Uniswap V3 Pools\n/// @notice A contract that constructs a pool must implement this to pass arguments to the pool\n/// @dev This is used to avoid having constructor arguments in the pool contract, which results in the init code hash\n/// of the pool being constant allowing the CREATE2 address of the pool to be cheaply computed on-chain\ninterface IUniswapV3PoolDeployer {\n /// @notice Get the parameters to be used in constructing the pool, set transiently during pool creation.\n /// @dev Called by the pool constructor to fetch the parameters of the pool\n /// Returns factory The factory address\n /// Returns token0 The first token of the pool by address sort order\n /// Returns token1 The second token of the pool by address sort order\n /// Returns fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// Returns tickSpacing The minimum number of ticks between initialized ticks\n function parameters()\n external\n view\n returns (\n address factory,\n address token0,\n address token1,\n uint24 fee,\n int24 tickSpacing\n );\n}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/interfaces/callback/IUniswapV3MintCallback.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Callback for IUniswapV3PoolActions#mint\n/// @notice Any contract that calls IUniswapV3PoolActions#mint must implement this interface\ninterface IUniswapV3MintCallback {\n /// @notice Called to `msg.sender` after minting liquidity to a position from IUniswapV3Pool#mint.\n /// @dev In the implementation you must pay the pool tokens owed for the minted liquidity.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// @param amount0Owed The amount of token0 due to the pool for the minted liquidity\n /// @param amount1Owed The amount of token1 due to the pool for the minted liquidity\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#mint call\n function uniswapV3MintCallback(\n uint256 amount0Owed,\n uint256 amount1Owed,\n bytes calldata data\n ) external;\n}\n" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "contracts/libraries/FundingPayment.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\n\nimport { SafeCast } from './SafeCast.sol';\nimport { SignedFullMath } from './SignedFullMath.sol';\n\n/// @title Funding payment functions\n/// @notice Funding Payment Logic used to distribute the FP bill paid by traders among the LPs in the liquidity range\nlibrary FundingPayment {\n using FullMath for uint256;\n using SafeCast for uint256;\n using SignedFullMath for int256;\n\n struct Info {\n // FR * P * dt\n int256 sumAX128;\n // trade token amount / liquidity\n int256 sumBX128;\n // sum(a * sumB)\n int256 sumFpX128;\n // time when state was last updated\n uint48 timestampLast;\n }\n\n event FundingPaymentStateUpdated(\n FundingPayment.Info fundingPayment,\n int256 fundingRateX128,\n uint256 virtualPriceX128\n );\n\n /// @notice Calculates the funding rate based on prices\n /// @param realPriceX128 spot price of token\n /// @param virtualPriceX128 futures price of token\n function getFundingRate(uint256 realPriceX128, uint256 virtualPriceX128)\n internal\n pure\n returns (int256 fundingRateX128)\n {\n int256 priceDeltaX128 = virtualPriceX128.toInt256() - realPriceX128.toInt256();\n return priceDeltaX128.mulDiv(FixedPoint128.Q128, realPriceX128) / 1 days;\n }\n\n /// @notice Used to update the state of the funding payment whenever a trade takes place\n /// @param info pointer to the funding payment state\n /// @param vTokenAmount trade token amount\n /// @param liquidity active liquidity in the range during the trade (step)\n /// @param blockTimestamp timestamp of current block\n /// @param fundingRateX128 the constant funding rate to apply for the duration between timestampLast and blockTimestamp\n /// @param virtualPriceX128 futures price of token\n function update(\n FundingPayment.Info storage info,\n int256 vTokenAmount,\n uint256 liquidity,\n uint48 blockTimestamp,\n int256 fundingRateX128,\n uint256 virtualPriceX128\n ) internal {\n int256 a = nextAX128(info.timestampLast, blockTimestamp, fundingRateX128, virtualPriceX128);\n info.sumFpX128 += a.mulDivRoundingDown(info.sumBX128, int256(FixedPoint128.Q128));\n info.sumAX128 += a;\n info.sumBX128 += vTokenAmount.mulDiv(int256(FixedPoint128.Q128), int256(liquidity));\n info.timestampLast = blockTimestamp;\n\n emit FundingPaymentStateUpdated(info, fundingRateX128, virtualPriceX128);\n }\n\n /// @notice Used to get the rate of funding payment for the duration between last trade and this trade\n /// @dev Positive A value means at this duration, longs pay shorts. Negative means shorts pay longs.\n /// @param timestampLast start timestamp of duration\n /// @param blockTimestamp end timestamp of duration\n /// @param virtualPriceX128 futures price of token\n /// @param fundingRateX128 the constant funding rate to apply for the duration between timestampLast and blockTimestamp\n /// @return aX128 value called \"a\" (see funding payment math documentation)\n function nextAX128(\n uint48 timestampLast,\n uint48 blockTimestamp,\n int256 fundingRateX128,\n uint256 virtualPriceX128\n ) internal pure returns (int256 aX128) {\n return fundingRateX128.mulDiv(virtualPriceX128, FixedPoint128.Q128) * int48(blockTimestamp - timestampLast);\n }\n\n function extrapolatedSumAX128(\n int256 sumAX128,\n uint48 timestampLast,\n uint48 blockTimestamp,\n int256 fundingRateX128,\n uint256 virtualPriceX128\n ) internal pure returns (int256) {\n return sumAX128 + nextAX128(timestampLast, blockTimestamp, fundingRateX128, virtualPriceX128);\n }\n\n /// @notice Extrapolates (updates) the value of sumFp by adding the missing component to it using sumAGlobalX128\n /// @param sumAX128 sumA value that is recorded from global at some point in time\n /// @param sumBX128 sumB value that is recorded from global at same point in time as sumA\n /// @param sumFpX128 sumFp value that is recorded from global at same point in time as sumA and sumB\n /// @param sumAGlobalX128 latest sumA value (taken from global), used to extrapolate the sumFp\n function extrapolatedSumFpX128(\n int256 sumAX128,\n int256 sumBX128,\n int256 sumFpX128,\n int256 sumAGlobalX128\n ) internal pure returns (int256) {\n return sumFpX128 + sumBX128.mulDiv(sumAGlobalX128 - sumAX128, int256(FixedPoint128.Q128));\n }\n\n /// @notice Positive bill is charged from LPs, Negative bill is rewarded to LPs\n /// @param sumAX128 latest value of sumA (to be taken from global state)\n /// @param sumFpInsideX128 latest value of sumFp inside range (to be computed using global state + tick state)\n /// @param sumALastX128 value of sumA when LP updated their liquidity last time\n /// @param sumBInsideLastX128 value of sumB inside range when LP updated their liquidity last time\n /// @param sumFpInsideLastX128 value of sumFp inside range when LP updated their liquidity last time\n /// @param liquidity amount of liquidity which was constant for LP in the time duration\n /// @return amount of vQuote tokens that should be charged if positive\n function bill(\n int256 sumAX128,\n int256 sumFpInsideX128,\n int256 sumALastX128,\n int256 sumBInsideLastX128,\n int256 sumFpInsideLastX128,\n uint256 liquidity\n ) internal pure returns (int256) {\n return\n (sumFpInsideX128 - extrapolatedSumFpX128(sumALastX128, sumBInsideLastX128, sumFpInsideLastX128, sumAX128))\n .mulDivRoundingDown(liquidity, FixedPoint128.Q128);\n }\n\n /// @notice Positive bill is charged from Traders, Negative bill is rewarded to Traders\n /// @param sumAX128 latest value of sumA (to be taken from global state)\n /// @param sumALastX128 value of sumA when trader updated their netTraderPosition\n /// @param netTraderPosition oken amount which should be constant for time duration since sumALastX128 was recorded\n /// @return amount of vQuote tokens that should be charged if positive\n function bill(\n int256 sumAX128,\n int256 sumALastX128,\n int256 netTraderPosition\n ) internal pure returns (int256) {\n return netTraderPosition.mulDiv((sumAX128 - sumALastX128), int256(FixedPoint128.Q128));\n }\n}\n" + }, + "contracts/libraries/SimulateSwap.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.4;\n\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { SwapMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/SwapMath.sol';\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\nimport { TickBitmapExtended } from './TickBitmapExtended.sol';\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\n/// @title Simulate Uniswap V3 Swaps\nlibrary SimulateSwap {\n using SafeCast for uint256;\n using TickBitmapExtended for function(int16) external view returns (uint256);\n\n error ZeroAmount();\n error InvalidSqrtPriceLimit(uint160 sqrtPriceLimitX96);\n\n struct Cache {\n // price at the beginning of the swap\n uint160 sqrtPriceX96Start;\n // tick at the beginning of the swap\n int24 tickStart;\n // the protocol fee for the input token\n uint8 feeProtocol;\n // liquidity at the beginning of the swap\n uint128 liquidityStart;\n // the tick spacing of the pool\n int24 tickSpacing;\n // the lp fee share of the pool\n uint24 fee;\n // extra values for cache, that may be useful for _onSwapStep\n uint256 value1;\n uint256 value2;\n }\n\n struct State {\n // the amount remaining to be swapped in/out of the input/output asset\n int256 amountSpecifiedRemaining;\n // the amount already swapped out/in of the output/input asset\n int256 amountCalculated;\n // current sqrt(price)\n uint160 sqrtPriceX96;\n // the tick associated with the current price\n int24 tick;\n // the global fee growth of the input token\n uint256 feeGrowthGlobalIncreaseX128;\n // amount of input token paid as protocol fee\n uint128 protocolFee;\n // the current liquidity in range\n uint128 liquidity;\n }\n\n struct Step {\n // the price at the beginning of the step\n uint160 sqrtPriceStartX96;\n // the next tick to swap to from the current tick in the swap direction\n int24 tickNext;\n // whether tickNext is initialized or not\n bool initialized;\n // sqrt(price) for the next tick (1/0)\n uint160 sqrtPriceNextX96;\n // how much is being swapped in in this step\n uint256 amountIn;\n // how much is being swapped out\n uint256 amountOut;\n // how much fee is being paid in\n uint256 feeAmount;\n }\n\n /// @notice Simulates a swap over an Uniswap V3 Pool, allowing to handle tick crosses.\n /// @param v3Pool uniswap v3 pool address\n /// @param zeroForOne direction of swap, true means swap zero for one\n /// @param amountSpecified amount to swap in/out\n /// @param sqrtPriceLimitX96 the maximum price to swap to, if this price is reached, then the swap is stopped partially\n /// @param cache the swap cache, can be passed empty or with some values filled in to prevent STATICCALLS to v3Pool\n /// @param onSwapStep function to call for each step of the swap, passing in the swap state and the step computations\n /// @return amount0 token0 amount\n /// @return amount1 token1 amount\n /// @return state swap state at the end of the swap\n function simulateSwap(\n IUniswapV3Pool v3Pool,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n SimulateSwap.Cache memory cache,\n function(bool, SimulateSwap.Cache memory, SimulateSwap.State memory, SimulateSwap.Step memory) onSwapStep\n )\n internal\n returns (\n int256 amount0,\n int256 amount1,\n SimulateSwap.State memory state\n )\n {\n if (amountSpecified == 0) revert ZeroAmount();\n\n // if cache.sqrtPriceX96Start is not set, then make a STATICCALL to v3Pool\n if (cache.sqrtPriceX96Start == 0) {\n (cache.sqrtPriceX96Start, cache.tickStart, , , , cache.feeProtocol, ) = v3Pool.slot0();\n }\n\n // if cache.liquidityStart is not set, then make a STATICCALL to v3Pool\n if (cache.liquidityStart == 0) cache.liquidityStart = v3Pool.liquidity();\n\n // if cache.tickSpacing is not set, then make a STATICCALL to v3Pool\n if (cache.tickSpacing == 0) {\n cache.fee = v3Pool.fee();\n cache.tickSpacing = v3Pool.tickSpacing();\n }\n\n // ensure that the sqrtPriceLimitX96 makes sense\n if (\n zeroForOne\n ? sqrtPriceLimitX96 > cache.sqrtPriceX96Start || sqrtPriceLimitX96 < TickMath.MIN_SQRT_RATIO\n : sqrtPriceLimitX96 < cache.sqrtPriceX96Start || sqrtPriceLimitX96 > TickMath.MAX_SQRT_RATIO\n ) revert InvalidSqrtPriceLimit(sqrtPriceLimitX96);\n\n bool exactInput = amountSpecified > 0;\n\n state = SimulateSwap.State({\n amountSpecifiedRemaining: amountSpecified,\n amountCalculated: 0,\n sqrtPriceX96: cache.sqrtPriceX96Start,\n tick: cache.tickStart,\n feeGrowthGlobalIncreaseX128: 0,\n protocolFee: 0,\n liquidity: cache.liquidityStart\n });\n\n // continue swapping as long as we haven't used the entire input/output and haven't reached the price limit\n while (state.amountSpecifiedRemaining != 0 && state.sqrtPriceX96 != sqrtPriceLimitX96) {\n SimulateSwap.Step memory step;\n\n step.sqrtPriceStartX96 = state.sqrtPriceX96;\n\n (step.tickNext, step.initialized) = v3Pool.tickBitmap.nextInitializedTickWithinOneWord(\n state.tick,\n cache.tickSpacing,\n zeroForOne\n );\n\n // ensure that we do not overshoot the min/max tick, as the tick bitmap is not aware of these bounds\n if (step.tickNext < TickMath.MIN_TICK) {\n step.tickNext = TickMath.MIN_TICK;\n } else if (step.tickNext > TickMath.MAX_TICK) {\n step.tickNext = TickMath.MAX_TICK;\n }\n\n // get the price for the next tick\n step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext);\n\n // compute values to swap to the target tick, price limit, or point where input/output amount is exhausted\n (state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep(\n state.sqrtPriceX96,\n (zeroForOne ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 : step.sqrtPriceNextX96 > sqrtPriceLimitX96)\n ? sqrtPriceLimitX96\n : step.sqrtPriceNextX96,\n state.liquidity,\n state.amountSpecifiedRemaining,\n cache.fee\n );\n\n if (exactInput) {\n state.amountSpecifiedRemaining -= (step.amountIn + step.feeAmount).toInt256();\n state.amountCalculated = state.amountCalculated - step.amountOut.toInt256();\n } else {\n state.amountSpecifiedRemaining += step.amountOut.toInt256();\n state.amountCalculated = state.amountCalculated + (step.amountIn + step.feeAmount).toInt256();\n }\n\n // update global fee tracker\n if (state.liquidity > 0) {\n state.feeGrowthGlobalIncreaseX128 += FullMath.mulDiv(\n step.feeAmount,\n FixedPoint128.Q128,\n state.liquidity\n );\n }\n\n // jump to the method that handles the swap step\n onSwapStep(zeroForOne, cache, state, step);\n\n // shift tick if we reached the next price\n if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {\n // if the tick is initialized, adjust the liquidity\n if (step.initialized) {\n (, int128 liquidityNet, , , , , , ) = v3Pool.ticks(step.tickNext);\n // if we're moving leftward, we interpret liquidityNet as the opposite sign\n // safe because liquidityNet cannot be type(int128).min\n if (zeroForOne) liquidityNet = -liquidityNet;\n state.liquidity = liquidityNet < 0\n ? state.liquidity - uint128(-liquidityNet)\n : state.liquidity + uint128(liquidityNet);\n }\n\n state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;\n } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) {\n // recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved\n state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96);\n }\n }\n\n (amount0, amount1) = zeroForOne == exactInput\n ? (amountSpecified - state.amountSpecifiedRemaining, state.amountCalculated)\n : (state.amountCalculated, amountSpecified - state.amountSpecifiedRemaining);\n }\n\n /// @notice Overloads simulate swap to prevent passing a cache input\n /// @param v3Pool uniswap v3 pool address\n /// @param zeroForOne direction of swap, true means swap zero for one\n /// @param amountSpecified amount to swap in/out\n /// @param sqrtPriceLimitX96 the maximum price to swap to, if this price is reached, then the swap is stopped partially\n /// @param onSwapStep function to call for each step of the swap, passing in the swap state and the step computations\n /// @return amount0 token0 amount\n /// @return amount1 token1 amount\n /// @return state swap state at the end of the swap\n /// @return cache swap cache populated with values, can be used for subsequent simulations\n function simulateSwap(\n IUniswapV3Pool v3Pool,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n function(bool, SimulateSwap.Cache memory, SimulateSwap.State memory, SimulateSwap.Step memory) onSwapStep\n )\n internal\n returns (\n int256 amount0,\n int256 amount1,\n SimulateSwap.State memory state,\n SimulateSwap.Cache memory cache\n )\n {\n (amount0, amount1, state) = simulateSwap(\n v3Pool,\n zeroForOne,\n amountSpecified,\n sqrtPriceLimitX96,\n cache,\n onSwapStep\n );\n }\n}\n" + }, + "contracts/libraries/PriceMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\n\nimport { Bisection } from './Bisection.sol';\n\n/// @title Price math functions\nlibrary PriceMath {\n using FullMath for uint256;\n\n error IllegalSqrtPrice(uint160 sqrtPriceX96);\n\n /// @notice Computes the square of a sqrtPriceX96 value\n /// @param sqrtPriceX96: the square root of the input price in Q96 format\n /// @return priceX128 : input price in Q128 format\n function toPriceX128(uint160 sqrtPriceX96) internal pure returns (uint256 priceX128) {\n if (sqrtPriceX96 < TickMath.MIN_SQRT_RATIO || sqrtPriceX96 >= TickMath.MAX_SQRT_RATIO) {\n revert IllegalSqrtPrice(sqrtPriceX96);\n }\n\n priceX128 = _toPriceX128(sqrtPriceX96);\n }\n\n /// @notice computes the square of a sqrtPriceX96 value\n /// @param sqrtPriceX96: input price in Q128 format\n function _toPriceX128(uint160 sqrtPriceX96) private pure returns (uint256 priceX128) {\n priceX128 = uint256(sqrtPriceX96).mulDiv(sqrtPriceX96, 1 << 64);\n }\n\n /// @notice computes the square root of a priceX128 value\n /// @param priceX128: input price in Q128 format\n /// @return sqrtPriceX96 : the square root of the input price in Q96 format\n function toSqrtPriceX96(uint256 priceX128) internal pure returns (uint160 sqrtPriceX96) {\n // Uses bisection method to find solution to the equation toPriceX128(x) = priceX128\n sqrtPriceX96 = Bisection.findSolution(\n _toPriceX128,\n priceX128,\n /// @dev sqrtPriceX96 is always bounded by MIN_SQRT_RATIO and MAX_SQRT_RATIO.\n /// If solution falls outside of these bounds, findSolution method reverts\n TickMath.MIN_SQRT_RATIO,\n TickMath.MAX_SQRT_RATIO - 1\n );\n }\n}\n" + }, + "contracts/libraries/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nint256 constant ONE = 1;\n\n/// @title Signed math functions\nlibrary SignedMath {\n /// @notice gives the absolute value of a signed int\n /// @param value signed int\n /// @return absolute value of signed int\n function abs(int256 value) internal pure returns (int256) {\n return value > 0 ? value : -value;\n }\n\n /// @notice gives the absolute value of a signed int\n /// @param value signed int\n /// @return absolute value of signed int as unsigned int\n function absUint(int256 value) internal pure returns (uint256) {\n return uint256(abs(value));\n }\n\n /// @notice gives the sign of a signed int\n /// @param value signed int\n /// @return -1 if negative, 1 if non-negative\n function sign(int256 value) internal pure returns (int256) {\n return value >= 0 ? ONE : -ONE;\n }\n\n /// @notice converts a signed integer into an unsigned integer and inverts positive bool if negative\n /// @param a signed int\n /// @param positive initial value of positive bool\n /// @return _a absolute value of int provided\n /// @return bool xor of the positive boolean and sign of the provided int\n function extractSign(int256 a, bool positive) internal pure returns (uint256 _a, bool) {\n if (a < 0) {\n positive = !positive;\n _a = uint256(-a);\n } else {\n _a = uint256(a);\n }\n return (_a, positive);\n }\n\n /// @notice extracts the sign of a signed int\n /// @param a signed int\n /// @return _a unsigned int\n /// @return bool sign of the provided int\n function extractSign(int256 a) internal pure returns (uint256 _a, bool) {\n return extractSign(a, true);\n }\n\n /// @notice returns the max of two int256 numbers\n /// @param a first number\n /// @param b second number\n /// @return c = max of a and b\n function max(int256 a, int256 b) internal pure returns (int256 c) {\n if (a > b) c = a;\n else c = b;\n }\n}\n" + }, + "contracts/libraries/SignedFullMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.0;\n\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\n\nimport { SignedMath } from './SignedMath.sol';\n\n/// @title Signed full math functions\nlibrary SignedFullMath {\n using SafeCast for uint256;\n using SignedMath for int256;\n\n /// @notice uses full math on signed int and two unsigned ints\n /// @param a: signed int\n /// @param b: unsigned int to be multiplied by\n /// @param denominator: unsigned int to be divided by\n /// @return result of a * b / denominator\n function mulDiv(\n int256 a,\n uint256 b,\n uint256 denominator\n ) internal pure returns (int256 result) {\n result = FullMath.mulDiv(a < 0 ? uint256(-1 * a) : uint256(a), b, denominator).toInt256();\n if (a < 0) {\n result = -result;\n }\n }\n\n /// @notice uses full math on three signed ints\n /// @param a: signed int\n /// @param b: signed int to be multiplied by\n /// @param denominator: signed int to be divided by\n /// @return result of a * b / denominator\n function mulDiv(\n int256 a,\n int256 b,\n int256 denominator\n ) internal pure returns (int256 result) {\n bool resultPositive = true;\n uint256 _a;\n uint256 _b;\n uint256 _denominator;\n\n (_a, resultPositive) = a.extractSign(resultPositive);\n (_b, resultPositive) = b.extractSign(resultPositive);\n (_denominator, resultPositive) = denominator.extractSign(resultPositive);\n\n result = FullMath.mulDiv(_a, _b, _denominator).toInt256();\n if (!resultPositive) {\n result = -result;\n }\n }\n\n /// @notice rounds down towards negative infinity\n /// @dev in Solidity -3/2 is -1. But this method result is -2\n /// @param a: signed int\n /// @param b: unsigned int to be multiplied by\n /// @param denominator: unsigned int to be divided by\n /// @return result of a * b / denominator rounded towards negative infinity\n function mulDivRoundingDown(\n int256 a,\n uint256 b,\n uint256 denominator\n ) internal pure returns (int256 result) {\n result = mulDiv(a, b, denominator);\n if (result < 0 && _hasRemainder(a.absUint(), b, denominator)) {\n result += -1;\n }\n }\n\n /// @notice rounds down towards negative infinity\n /// @dev in Solidity -3/2 is -1. But this method result is -2\n /// @param a: signed int\n /// @param b: signed int to be multiplied by\n /// @param denominator: signed int to be divided by\n /// @return result of a * b / denominator rounded towards negative infinity\n function mulDivRoundingDown(\n int256 a,\n int256 b,\n int256 denominator\n ) internal pure returns (int256 result) {\n result = mulDiv(a, b, denominator);\n if (result < 0 && _hasRemainder(a.absUint(), b.absUint(), denominator.absUint())) {\n result += -1;\n }\n }\n\n /// @notice checks if full multiplication of a & b would have a remainder if divided by denominator\n /// @param a: multiplicand\n /// @param b: multiplier\n /// @param denominator: divisor\n /// @return hasRemainder true if there is a remainder, false otherwise\n function _hasRemainder(\n uint256 a,\n uint256 b,\n uint256 denominator\n ) private pure returns (bool hasRemainder) {\n assembly {\n let remainder := mulmod(a, b, denominator)\n if gt(remainder, 0) {\n hasRemainder := 1\n }\n }\n }\n}\n" + }, + "contracts/libraries/UniswapV3PoolHelper.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\n/// @title UniswapV3Pool helper functions\nlibrary UniswapV3PoolHelper {\n using UniswapV3PoolHelper for IUniswapV3Pool;\n\n error UV3PH_OracleConsultFailed();\n\n /// @notice Get the pool's current tick\n /// @param v3Pool The uniswap v3 pool contract\n /// @return tick the current tick\n function tickCurrent(IUniswapV3Pool v3Pool) internal view returns (int24 tick) {\n (, tick, , , , , ) = v3Pool.slot0();\n }\n\n /// @notice Get the pool's current sqrt price\n /// @param v3Pool The uniswap v3 pool contract\n /// @return sqrtPriceX96 the current sqrt price\n function sqrtPriceCurrent(IUniswapV3Pool v3Pool) internal view returns (uint160 sqrtPriceX96) {\n (sqrtPriceX96, , , , , , ) = v3Pool.slot0();\n }\n\n /// @notice Get twap price for uniswap v3 pool\n /// @param v3Pool The uniswap v3 pool contract\n /// @param twapDuration The twap period\n /// @return sqrtPriceX96 the twap price\n function twapSqrtPrice(IUniswapV3Pool v3Pool, uint32 twapDuration) internal view returns (uint160 sqrtPriceX96) {\n int24 _twapTick = v3Pool.twapTick(twapDuration);\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_twapTick);\n }\n\n /// @notice Get twap tick for uniswap v3 pool\n /// @param v3Pool The uniswap v3 pool contract\n /// @param twapDuration The twap period\n /// @return _twapTick the twap tick\n function twapTick(IUniswapV3Pool v3Pool, uint32 twapDuration) internal view returns (int24 _twapTick) {\n if (twapDuration == 0) {\n return v3Pool.tickCurrent();\n }\n\n uint32[] memory secondAgos = new uint32[](2);\n secondAgos[0] = twapDuration;\n secondAgos[1] = 0;\n\n // this call will fail if period is bigger than MaxObservationPeriod\n try v3Pool.observe(secondAgos) returns (int56[] memory tickCumulatives, uint160[] memory) {\n int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\n int24 timeWeightedAverageTick = int24(tickCumulativesDelta / int56(uint56(twapDuration)));\n\n // Always round to negative infinity\n if (tickCumulativesDelta < 0 && (tickCumulativesDelta % int56(uint56(twapDuration)) != 0)) {\n timeWeightedAverageTick--;\n }\n return timeWeightedAverageTick;\n } catch {\n // if for some reason v3Pool.observe fails, fallback to the current tick\n (, _twapTick, , , , , ) = v3Pool.slot0();\n }\n }\n}\n" + }, + "contracts/protocol/wrapper/VPoolWrapper.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.14;\n\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\nimport { IUniswapV3MintCallback } from '@uniswap/v3-core-0.8-support/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\nimport { IUniswapV3SwapCallback } from '@uniswap/v3-core-0.8-support/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\n\nimport { IVPoolWrapper } from '../../interfaces/IVPoolWrapper.sol';\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\nimport { IVToken } from '../../interfaces/IVToken.sol';\nimport { IVToken } from '../../interfaces/IVToken.sol';\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\nimport { IClearingHouseStructures } from '../../interfaces/clearinghouse/IClearingHouseStructures.sol';\n\nimport { AddressHelper } from '../../libraries/AddressHelper.sol';\nimport { FundingPayment } from '../../libraries/FundingPayment.sol';\nimport { SimulateSwap } from '../../libraries/SimulateSwap.sol';\nimport { TickExtended } from '../../libraries/TickExtended.sol';\nimport { PriceMath } from '../../libraries/PriceMath.sol';\nimport { SafeCast } from '../../libraries/SafeCast.sol';\nimport { SignedMath } from '../../libraries/SignedMath.sol';\nimport { SignedFullMath } from '../../libraries/SignedFullMath.sol';\nimport { SwapMath } from '../../libraries/SwapMath.sol';\nimport { UniswapV3PoolHelper } from '../../libraries/UniswapV3PoolHelper.sol';\n\nimport { Extsload } from '../../utils/Extsload.sol';\n\nimport { UNISWAP_V3_DEFAULT_TICKSPACING, UNISWAP_V3_DEFAULT_FEE_TIER } from '../../utils/constants.sol';\n\ncontract VPoolWrapper is IVPoolWrapper, IUniswapV3MintCallback, IUniswapV3SwapCallback, Initializable, Extsload {\n using AddressHelper for IVToken;\n using FullMath for uint256;\n using FundingPayment for FundingPayment.Info;\n using SignedMath for int256;\n using SignedFullMath for int256;\n using PriceMath for uint160;\n using SafeCast for uint256;\n using SafeCast for uint128;\n using SimulateSwap for IUniswapV3Pool;\n using TickExtended for IUniswapV3Pool;\n using TickExtended for mapping(int24 => TickExtended.Info);\n using UniswapV3PoolHelper for IUniswapV3Pool;\n\n IClearingHouse public clearingHouse;\n IVToken public vToken;\n IVQuote public vQuote;\n IUniswapV3Pool public vPool;\n\n uint24 constant PERC_10_1E6 = 100000;\n\n // fee paid to liquidity providers, in 1e6\n uint24 public liquidityFeePips;\n // fee paid to DAO treasury\n uint24 public protocolFeePips;\n\n uint256 public accruedProtocolFee;\n\n FundingPayment.Info public fpGlobal;\n uint256 public sumFeeGlobalX128;\n\n int256 constant FUNDING_RATE_OVERRIDE_NULL_VALUE = type(int256).max;\n int256 public fundingRateOverrideX128;\n\n mapping(int24 => TickExtended.Info) public ticksExtended;\n\n error NotClearingHouse();\n error NotGovernance();\n error NotGovernanceOrTeamMultisig();\n error NotUniswapV3Pool();\n error InvalidTicks(int24 tickLower, int24 tickUpper);\n error InvalidSetting(uint256 errorCode);\n\n modifier onlyClearingHouse() {\n if (msg.sender != address(clearingHouse)) {\n revert NotClearingHouse();\n }\n _;\n }\n\n modifier onlyGovernance() {\n if (msg.sender != clearingHouse.governance()) {\n revert NotGovernance();\n }\n _;\n }\n\n modifier onlyGovernanceOrTeamMultisig() {\n if (msg.sender != clearingHouse.governance() && msg.sender != clearingHouse.teamMultisig()) {\n revert NotGovernanceOrTeamMultisig();\n }\n _;\n }\n\n modifier onlyUniswapV3Pool() {\n if (msg.sender != address(vPool)) {\n revert NotUniswapV3Pool();\n }\n _;\n }\n\n modifier checkTicks(int24 tickLower, int24 tickUpper) {\n if (\n tickLower >= tickUpper ||\n tickLower < TickMath.MIN_TICK ||\n tickUpper > TickMath.MAX_TICK ||\n tickLower % UNISWAP_V3_DEFAULT_TICKSPACING != 0 ||\n tickUpper % UNISWAP_V3_DEFAULT_TICKSPACING != 0\n ) revert InvalidTicks(tickLower, tickUpper);\n _;\n }\n\n /**\n PLATFORM FUNCTIONS\n */\n\n function initialize(InitializeVPoolWrapperParams calldata params) external initializer {\n clearingHouse = IClearingHouse(params.clearingHouse);\n vToken = params.vToken;\n vQuote = params.vQuote;\n vPool = params.vPool;\n\n liquidityFeePips = params.liquidityFeePips;\n protocolFeePips = params.protocolFeePips;\n\n fundingRateOverrideX128 = type(int256).max;\n\n // initializes the funding payment state by zeroing the funding payment for time 0 to blockTimestamp\n fpGlobal.update({\n vTokenAmount: 0,\n liquidity: 1,\n blockTimestamp: _blockTimestamp(),\n virtualPriceX128: 1,\n fundingRateX128: 0 // causes zero funding payment\n });\n }\n\n function collectAccruedProtocolFee() external onlyClearingHouse returns (uint256 accruedProtocolFeeLast) {\n // check for underflow (to skip if accruedProtocolFee is 0)\n if (accruedProtocolFee != 0) {\n accruedProtocolFeeLast = accruedProtocolFee - 1;\n accruedProtocolFee = 1;\n }\n emit AccruedProtocolFeeCollected(accruedProtocolFeeLast);\n }\n\n /// @notice Update the global funding state, from clearing house\n /// @dev Done when clearing house is paused or unpaused, to prevent funding payments from being received\n /// or paid when clearing house is in paused mode.\n function updateGlobalFundingState(bool useZeroFundingRate) public onlyClearingHouse {\n (int256 fundingRateX128, uint256 virtualPriceX128) = getFundingRateAndVirtualPrice();\n fpGlobal.update({\n vTokenAmount: 0,\n liquidity: 1,\n blockTimestamp: _blockTimestamp(),\n virtualPriceX128: virtualPriceX128,\n fundingRateX128: useZeroFundingRate ? int256(0) : fundingRateX128\n });\n }\n\n /**\n ADMIN FUNCTIONS\n */\n\n function setLiquidityFee(uint24 liquidityFeePips_) external onlyGovernance {\n if (liquidityFeePips_ > PERC_10_1E6) revert InvalidSetting(0x10);\n liquidityFeePips = liquidityFeePips_;\n emit LiquidityFeeUpdated(liquidityFeePips_);\n }\n\n function setProtocolFee(uint24 protocolFeePips_) external onlyGovernance {\n if (protocolFeePips_ > PERC_10_1E6) revert InvalidSetting(0x20);\n protocolFeePips = protocolFeePips_;\n emit ProtocolFeeUpdated(protocolFeePips_);\n }\n\n function setFundingRateOverride(int256 fundingRateOverrideX128_) external onlyGovernanceOrTeamMultisig {\n uint256 fundingRateOverrideX128Abs = fundingRateOverrideX128_.absUint();\n // ensure that funding rate magnitude is < 100% APR\n if (\n fundingRateOverrideX128_ != FUNDING_RATE_OVERRIDE_NULL_VALUE &&\n fundingRateOverrideX128Abs > FixedPoint128.Q128 / (365 days)\n ) revert InvalidSetting(0x30);\n fundingRateOverrideX128 = fundingRateOverrideX128_;\n emit FundingRateOverrideUpdated(fundingRateOverrideX128_);\n }\n\n /**\n EXTERNAL UTILITY METHODS\n */\n\n /// @notice Swap vToken for vQuote, or vQuote for vToken\n /// @param swapVTokenForVQuote: The direction of the swap, true for vToken to vQuote, false for vQuote to vToken\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 /// @return swapResult swap return values, which contain the execution details of the swap\n function swap(\n bool swapVTokenForVQuote, // zeroForOne\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96\n ) public onlyClearingHouse returns (SwapResult memory swapResult) {\n bool exactIn = amountSpecified >= 0;\n\n if (sqrtPriceLimitX96 == 0) {\n sqrtPriceLimitX96 = swapVTokenForVQuote ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1;\n }\n\n swapResult.amountSpecified = amountSpecified;\n\n SwapMath.beforeSwap(\n exactIn,\n swapVTokenForVQuote,\n UNISWAP_V3_DEFAULT_FEE_TIER,\n liquidityFeePips,\n protocolFeePips,\n swapResult\n );\n\n {\n SimulateSwap.Cache memory cache;\n cache.tickSpacing = UNISWAP_V3_DEFAULT_TICKSPACING;\n cache.fee = UNISWAP_V3_DEFAULT_FEE_TIER;\n (int256 fundingRateX128, uint256 virtualPriceX128) = getFundingRateAndVirtualPrice();\n _writeCacheExtraValues(cache, virtualPriceX128, fundingRateX128);\n\n // simulate swap and update our tick states\n (int256 vTokenIn_simulated, int256 vQuoteIn_simulated, SimulateSwap.State memory state) = vPool\n .simulateSwap(swapVTokenForVQuote, swapResult.amountSpecified, sqrtPriceLimitX96, cache, _onSwapStep);\n\n // store prices for the simulated swap in the swap result\n swapResult.sqrtPriceX96Start = cache.sqrtPriceX96Start;\n swapResult.sqrtPriceX96End = state.sqrtPriceX96;\n\n // execute actual swap on uniswap\n (swapResult.vTokenIn, swapResult.vQuoteIn) = vPool.swap(\n address(this),\n swapVTokenForVQuote,\n swapResult.amountSpecified,\n sqrtPriceLimitX96,\n ''\n );\n\n // simulated swap should be identical to actual swap\n assert(vTokenIn_simulated == swapResult.vTokenIn && vQuoteIn_simulated == swapResult.vQuoteIn);\n }\n\n SwapMath.afterSwap(\n exactIn,\n swapVTokenForVQuote,\n UNISWAP_V3_DEFAULT_FEE_TIER,\n liquidityFeePips,\n protocolFeePips,\n swapResult\n );\n\n // record the protocol fee, for withdrawal in future\n accruedProtocolFee += swapResult.protocolFees;\n\n // burn the tokens received from the swap\n _vBurn();\n\n emit Swap(swapResult);\n }\n\n function mint(\n int24 tickLower,\n int24 tickUpper,\n uint128 liquidity\n )\n external\n onlyClearingHouse\n checkTicks(tickLower, tickUpper)\n returns (\n uint256 vTokenPrincipal,\n uint256 vQuotePrincipal,\n WrapperValuesInside memory wrapperValuesInside\n )\n {\n // records the funding payment for last updated timestamp to blockTimestamp using current price difference\n _updateGlobalFundingState();\n\n wrapperValuesInside = _updateTicks(tickLower, tickUpper, liquidity.toInt128(), vPool.tickCurrent());\n\n (uint256 _amount0, uint256 _amount1) = vPool.mint({\n recipient: address(this),\n tickLower: tickLower,\n tickUpper: tickUpper,\n amount: liquidity,\n data: ''\n });\n\n vTokenPrincipal = _amount0;\n vQuotePrincipal = _amount1;\n }\n\n function burn(\n int24 tickLower,\n int24 tickUpper,\n uint128 liquidity\n )\n external\n onlyClearingHouse\n checkTicks(tickLower, tickUpper)\n returns (\n uint256 vTokenPrincipal,\n uint256 vQuotePrincipal,\n WrapperValuesInside memory wrapperValuesInside\n )\n {\n // records the funding payment for last updated timestamp to blockTimestamp using current price difference\n _updateGlobalFundingState();\n\n wrapperValuesInside = _updateTicks(tickLower, tickUpper, -liquidity.toInt128(), vPool.tickCurrent());\n\n (uint256 _amount0, uint256 _amount1) = vPool.burn({\n tickLower: tickLower,\n tickUpper: tickUpper,\n amount: liquidity\n });\n\n vTokenPrincipal = _amount0;\n vQuotePrincipal = _amount1;\n _collect(tickLower, tickUpper);\n }\n\n /**\n UNISWAP V3 POOL CALLBACkS\n */\n\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata\n ) external virtual onlyUniswapV3Pool {\n if (amount0Delta > 0) {\n // uniswap v3 pool token0 is always vToken (ensured in RageTradeFactory._isIVTokenAddressGood)\n IVToken(vPool.token0()).mint(address(vPool), uint256(amount0Delta));\n }\n if (amount1Delta > 0) {\n // uniswap v3 pool token1 is always vQuote (ensured in RageTradeFactory._isIVTokenAddressGood)\n IVQuote(vPool.token1()).mint(address(vPool), uint256(amount1Delta));\n }\n }\n\n function uniswapV3MintCallback(\n uint256 vTokenAmount,\n uint256 vQuoteAmount,\n bytes calldata\n ) external override onlyUniswapV3Pool {\n if (vQuoteAmount > 0) vQuote.mint(msg.sender, vQuoteAmount);\n if (vTokenAmount > 0) vToken.mint(msg.sender, vTokenAmount);\n }\n\n /**\n VIEW METHODS\n */\n\n function getFundingRateAndVirtualPrice() public view returns (int256 fundingRateX128, uint256 virtualPriceX128) {\n int256 _fundingRateOverrideX128 = fundingRateOverrideX128;\n bool shouldUseActualPrices = _fundingRateOverrideX128 == FUNDING_RATE_OVERRIDE_NULL_VALUE;\n\n uint32 poolId = vToken.truncate();\n virtualPriceX128 = clearingHouse.getVirtualTwapPriceX128(poolId);\n\n if (shouldUseActualPrices) {\n // uses actual price to calculate funding rate\n uint256 realPriceX128 = clearingHouse.getRealTwapPriceX128(poolId);\n fundingRateX128 = FundingPayment.getFundingRate(realPriceX128, virtualPriceX128);\n } else {\n // uses funding rate override\n fundingRateX128 = _fundingRateOverrideX128;\n }\n }\n\n function getSumAX128() external view returns (int256) {\n return fpGlobal.sumAX128;\n }\n\n function getExtrapolatedSumAX128() public view returns (int256) {\n (int256 fundingRateX128, uint256 virtualPriceX128) = getFundingRateAndVirtualPrice();\n return\n FundingPayment.extrapolatedSumAX128(\n fpGlobal.sumAX128,\n fpGlobal.timestampLast,\n _blockTimestamp(),\n fundingRateX128,\n virtualPriceX128\n );\n }\n\n function getValuesInside(int24 tickLower, int24 tickUpper)\n public\n view\n checkTicks(tickLower, tickUpper)\n returns (WrapperValuesInside memory wrapperValuesInside)\n {\n (, int24 currentTick, , , , , ) = vPool.slot0();\n FundingPayment.Info memory _fpGlobal = fpGlobal;\n wrapperValuesInside.sumAX128 = _fpGlobal.sumAX128;\n (\n wrapperValuesInside.sumBInsideX128,\n wrapperValuesInside.sumFpInsideX128,\n wrapperValuesInside.sumFeeInsideX128\n ) = ticksExtended.getTickExtendedStateInside(tickLower, tickUpper, currentTick, _fpGlobal, sumFeeGlobalX128);\n }\n\n function getExtrapolatedValuesInside(int24 tickLower, int24 tickUpper)\n external\n view\n returns (WrapperValuesInside memory wrapperValuesInside)\n {\n (, int24 currentTick, , , , , ) = vPool.slot0();\n FundingPayment.Info memory _fpGlobal = fpGlobal;\n\n ///@dev update sumA and sumFP to extrapolated values according to current timestamp\n _fpGlobal.sumAX128 = getExtrapolatedSumAX128();\n _fpGlobal.sumFpX128 = FundingPayment.extrapolatedSumFpX128(\n fpGlobal.sumAX128,\n fpGlobal.sumBX128,\n fpGlobal.sumFpX128,\n _fpGlobal.sumAX128\n );\n\n wrapperValuesInside.sumAX128 = _fpGlobal.sumAX128;\n (\n wrapperValuesInside.sumBInsideX128,\n wrapperValuesInside.sumFpInsideX128,\n wrapperValuesInside.sumFeeInsideX128\n ) = ticksExtended.getTickExtendedStateInside(tickLower, tickUpper, currentTick, _fpGlobal, sumFeeGlobalX128);\n }\n\n /**\n INTERNAL HELPERS\n */\n\n function _collect(int24 tickLower, int24 tickUpper) internal {\n // (uint256 amount0, uint256 amount1) =\n vPool.collect({\n recipient: address(this),\n tickLower: tickLower,\n tickUpper: tickUpper,\n amount0Requested: type(uint128).max,\n amount1Requested: type(uint128).max\n });\n\n _vBurn();\n }\n\n function _readCacheExtraValues(SimulateSwap.Cache memory cache)\n private\n pure\n returns (uint256 virtualPriceX128, int256 fundingRateX128)\n {\n uint256 value1 = cache.value1;\n uint256 value2 = cache.value2;\n assembly {\n virtualPriceX128 := value1\n fundingRateX128 := value2\n }\n }\n\n function _writeCacheExtraValues(\n SimulateSwap.Cache memory cache,\n uint256 virtualPriceX128,\n int256 fundingRateX128\n ) private pure {\n uint256 value1;\n uint256 value2;\n assembly {\n value1 := virtualPriceX128\n value2 := fundingRateX128\n }\n cache.value1 = value1;\n cache.value2 = value2;\n }\n\n function _onSwapStep(\n bool swapVTokenForVQuote,\n SimulateSwap.Cache memory cache,\n SimulateSwap.State memory state,\n SimulateSwap.Step memory step\n ) internal {\n // these vQuote and vToken amounts are zero fee swap amounts (fee collected by uniswaop is ignored and burned later)\n (uint256 vTokenAmount, uint256 vQuoteAmount) = swapVTokenForVQuote\n ? (step.amountIn, step.amountOut)\n : (step.amountOut, step.amountIn);\n\n // here, vQuoteAmount == swap amount\n (uint256 liquidityFees, ) = SwapMath.calculateFees(\n vQuoteAmount.toInt256(),\n SwapMath.AmountTypeEnum.ZERO_FEE_VQUOTE_AMOUNT,\n liquidityFeePips,\n protocolFeePips\n );\n\n // vQuote amount with fees\n // vQuoteAmount = _includeFees(\n // vQuoteAmount,\n // liquidityFees + protocolFees,\n // swapVTokenForVQuote ? IncludeFeeEnum.SUBTRACT_FEE : IncludeFeeEnum.ADD_FEE\n // );\n\n if (state.liquidity > 0 && vTokenAmount > 0) {\n (uint256 virtualPriceX128, int256 fundingRateX128) = _readCacheExtraValues(cache);\n fpGlobal.update({\n vTokenAmount: swapVTokenForVQuote ? vTokenAmount.toInt256() : -vTokenAmount.toInt256(), // when trader goes long, LP goes short\n liquidity: state.liquidity,\n blockTimestamp: _blockTimestamp(),\n virtualPriceX128: virtualPriceX128,\n fundingRateX128: fundingRateX128\n });\n\n sumFeeGlobalX128 += liquidityFees.mulDiv(FixedPoint128.Q128, state.liquidity);\n }\n\n // if we have reached the end price of tick\n if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {\n // if the tick is initialized, run the tick transition\n if (step.initialized) {\n ticksExtended.cross(step.tickNext, fpGlobal, sumFeeGlobalX128);\n }\n }\n }\n\n /// @notice Update global funding payment, by getting prices from Clearing House\n function _updateGlobalFundingState() internal {\n (int256 fundingRateX128, uint256 virtualPriceX128) = getFundingRateAndVirtualPrice();\n fpGlobal.update({\n vTokenAmount: 0,\n liquidity: 1,\n blockTimestamp: _blockTimestamp(),\n virtualPriceX128: virtualPriceX128,\n fundingRateX128: fundingRateX128\n });\n }\n\n function _updateTicks(\n int24 tickLower,\n int24 tickUpper,\n int128 liquidityDelta,\n int24 tickCurrent\n ) private returns (WrapperValuesInside memory wrapperValuesInside) {\n FundingPayment.Info memory _fpGlobal = fpGlobal; // SLOAD\n uint256 _sumFeeGlobalX128 = sumFeeGlobalX128;\n\n // if we need to update the ticks, do it\n bool flippedLower;\n bool flippedUpper;\n if (liquidityDelta != 0) {\n flippedLower = ticksExtended.update(\n tickLower,\n tickCurrent,\n liquidityDelta,\n _fpGlobal.sumAX128,\n _fpGlobal.sumBX128,\n _fpGlobal.sumFpX128,\n _sumFeeGlobalX128,\n vPool\n );\n flippedUpper = ticksExtended.update(\n tickUpper,\n tickCurrent,\n liquidityDelta,\n _fpGlobal.sumAX128,\n _fpGlobal.sumBX128,\n _fpGlobal.sumFpX128,\n _sumFeeGlobalX128,\n vPool\n );\n }\n\n wrapperValuesInside = getValuesInside(tickLower, tickUpper);\n\n // clear any tick data that is no longer needed\n if (liquidityDelta < 0) {\n if (flippedLower) {\n ticksExtended.clear(tickLower);\n }\n if (flippedUpper) {\n ticksExtended.clear(tickUpper);\n }\n }\n }\n\n function _vBurn() internal {\n uint256 vQuoteBal = vQuote.balanceOf(address(this));\n if (vQuoteBal > 0) {\n vQuote.burn(vQuoteBal);\n }\n uint256 vTokenBal = vToken.balanceOf(address(this));\n if (vTokenBal > 0) {\n vToken.burn(vTokenBal);\n }\n }\n\n // used to set time in tests\n function _blockTimestamp() internal view virtual returns (uint48) {\n return uint48(block.timestamp);\n }\n}\n" + }, + "contracts/libraries/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\n\n/// @title Safe cast functions\nlibrary SafeCast {\n error SafeCast_Int128Overflow(uint128 value);\n\n function toInt128(uint128 y) internal pure returns (int128 z) {\n unchecked {\n if (y >= 2**127) revert SafeCast_Int128Overflow(y);\n z = int128(y);\n }\n }\n\n error SafeCast_Int256Overflow(uint256 value);\n\n function toInt256(uint256 y) internal pure returns (int256 z) {\n unchecked {\n if (y >= 2**255) revert SafeCast_Int256Overflow(y);\n z = int256(y);\n }\n }\n\n error SafeCast_UInt224Overflow(uint256 value);\n\n function toUint224(uint256 y) internal pure returns (uint224 z) {\n if (y > 2**224) revert SafeCast_UInt224Overflow(y);\n z = uint224(y);\n }\n}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/libraries/SwapMath.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {FullMath} from './FullMath.sol';\nimport {SqrtPriceMath} from './SqrtPriceMath.sol';\n\n/// @title Computes the result of a swap within ticks\n/// @notice Contains methods for computing the result of a swap within a single tick price range, i.e., a single tick.\nlibrary SwapMath {\n /// @notice Computes the result of swapping some amount in, or amount out, given the parameters of the swap\n /// @dev The fee, plus the amount in, will never exceed the amount remaining if the swap's `amountSpecified` is positive\n /// @param sqrtRatioCurrentX96 The current sqrt price of the pool\n /// @param sqrtRatioTargetX96 The price that cannot be exceeded, from which the direction of the swap is inferred\n /// @param liquidity The usable liquidity\n /// @param amountRemaining How much input or output amount is remaining to be swapped in/out\n /// @param feePips The fee taken from the input amount, expressed in hundredths of a bip\n /// @return sqrtRatioNextX96 The price after swapping the amount in/out, not to exceed the price target\n /// @return amountIn The amount to be swapped in, of either token0 or token1, based on the direction of the swap\n /// @return amountOut The amount to be received, of either token0 or token1, based on the direction of the swap\n /// @return feeAmount The amount of input that will be taken as a fee\n function computeSwapStep(\n uint160 sqrtRatioCurrentX96,\n uint160 sqrtRatioTargetX96,\n uint128 liquidity,\n int256 amountRemaining,\n uint24 feePips\n )\n internal\n pure\n returns (\n uint160 sqrtRatioNextX96,\n uint256 amountIn,\n uint256 amountOut,\n uint256 feeAmount\n )\n {\n unchecked {\n bool zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96;\n bool exactIn = amountRemaining >= 0;\n\n if (exactIn) {\n uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(amountRemaining), 1e6 - feePips, 1e6);\n amountIn = zeroForOne\n ? SqrtPriceMath.getAmount0Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, true)\n : SqrtPriceMath.getAmount1Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, true);\n if (amountRemainingLessFee >= amountIn) sqrtRatioNextX96 = sqrtRatioTargetX96;\n else\n sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput(\n sqrtRatioCurrentX96,\n liquidity,\n amountRemainingLessFee,\n zeroForOne\n );\n } else {\n amountOut = zeroForOne\n ? SqrtPriceMath.getAmount1Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, false)\n : SqrtPriceMath.getAmount0Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, false);\n if (uint256(-amountRemaining) >= amountOut) sqrtRatioNextX96 = sqrtRatioTargetX96;\n else\n sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput(\n sqrtRatioCurrentX96,\n liquidity,\n uint256(-amountRemaining),\n zeroForOne\n );\n }\n\n bool max = sqrtRatioTargetX96 == sqrtRatioNextX96;\n\n // get the input/output amounts\n if (zeroForOne) {\n amountIn = max && exactIn\n ? amountIn\n : SqrtPriceMath.getAmount0Delta(sqrtRatioNextX96, sqrtRatioCurrentX96, liquidity, true);\n amountOut = max && !exactIn\n ? amountOut\n : SqrtPriceMath.getAmount1Delta(sqrtRatioNextX96, sqrtRatioCurrentX96, liquidity, false);\n } else {\n amountIn = max && exactIn\n ? amountIn\n : SqrtPriceMath.getAmount1Delta(sqrtRatioCurrentX96, sqrtRatioNextX96, liquidity, true);\n amountOut = max && !exactIn\n ? amountOut\n : SqrtPriceMath.getAmount0Delta(sqrtRatioCurrentX96, sqrtRatioNextX96, liquidity, false);\n }\n\n // cap the output amount to not exceed the remaining output amount\n if (!exactIn && amountOut > uint256(-amountRemaining)) {\n amountOut = uint256(-amountRemaining);\n }\n\n if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) {\n // we didn't reach the target, so take the remainder of the maximum input as fee\n feeAmount = uint256(amountRemaining) - amountIn;\n } else {\n feeAmount = FullMath.mulDivRoundingUp(amountIn, feePips, 1e6 - feePips);\n }\n }\n }\n}\n" + }, + "contracts/libraries/TickBitmapExtended.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport { BitMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/BitMath.sol';\n\n/// @title Tick bitmap extended functions\n/// @dev Uses the bitmap from UniswapV3Pool\nlibrary TickBitmapExtended {\n /// @notice Computes the position in the mapping where the initialized bit for a tick lives\n /// @param tick The tick for which to compute the position\n /// @return wordPos The key in the mapping containing the word in which the bit is stored\n /// @return bitPos The bit position in the word where the flag is stored\n function position(int24 tick) private pure returns (int16 wordPos, uint8 bitPos) {\n wordPos = int16(tick >> 8);\n bitPos = uint8(uint24(tick % 256));\n }\n\n /// @notice Returns the next initialized tick contained in the same word (or adjacent word) as the tick that is either\n /// to the left (less than or equal to) or right (greater than) of the given tick\n /// @param self The mapping in which to compute the next initialized tick\n /// @param tick The starting tick\n /// @param tickSpacing The spacing between usable ticks\n /// @param lte Whether to search for the next initialized tick to the left (less than or equal to the starting tick)\n /// @return next The next initialized or uninitialized tick up to 256 ticks away from the current tick\n /// @return initialized Whether the next tick is initialized, as the function only searches within up to 256 ticks\n function nextInitializedTickWithinOneWord(\n function(int16) external view returns (uint256) self,\n int24 tick,\n int24 tickSpacing,\n bool lte\n ) internal view returns (int24 next, bool initialized) {\n int24 compressed = tick / tickSpacing;\n if (tick < 0 && tick % tickSpacing != 0) compressed--; // round towards negative infinity\n\n if (lte) {\n (int16 wordPos, uint8 bitPos) = position(compressed);\n // all the 1s at or to the right of the current bitPos\n uint256 mask = (1 << bitPos) - 1 + (1 << bitPos);\n uint256 masked = self(wordPos) & mask;\n\n // if there are no initialized ticks to the right of or at the current tick, return rightmost in the word\n initialized = masked != 0;\n // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick\n next = initialized\n ? (compressed - int24(uint24(bitPos - BitMath.mostSignificantBit(masked)))) * tickSpacing\n : (compressed - int24(uint24(bitPos))) * tickSpacing;\n } else {\n // start from the word of the next tick, since the current tick state doesn't matter\n (int16 wordPos, uint8 bitPos) = position(compressed + 1);\n // all the 1s at or to the left of the bitPos\n uint256 mask = ~((1 << bitPos) - 1);\n uint256 masked = self(wordPos) & mask;\n\n // if there are no initialized ticks to the left of the current tick, return leftmost in the word\n initialized = masked != 0;\n // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick\n next = initialized\n ? (compressed + 1 + int24(uint24(BitMath.leastSignificantBit(masked) - bitPos))) * tickSpacing\n : (compressed + 1 + int24(uint24(type(uint8).max - bitPos))) * tickSpacing;\n }\n }\n}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/libraries/SqrtPriceMath.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {SafeCast} from './SafeCast.sol';\n\nimport {FullMath} from './FullMath.sol';\nimport {UnsafeMath} from './UnsafeMath.sol';\nimport {FixedPoint96} from './FixedPoint96.sol';\n\n/// @title Functions based on Q64.96 sqrt price and liquidity\n/// @notice Contains the math that uses square root of price as a Q64.96 and liquidity to compute deltas\nlibrary SqrtPriceMath {\n using SafeCast for uint256;\n\n /// @notice Gets the next sqrt price given a delta of token0\n /// @dev Always rounds up, because in the exact output case (increasing price) we need to move the price at least\n /// far enough to get the desired output amount, and in the exact input case (decreasing price) we need to move the\n /// price less in order to not send too much output.\n /// The most precise formula for this is liquidity * sqrtPX96 / (liquidity +- amount * sqrtPX96),\n /// if this is impossible because of overflow, we calculate liquidity / (liquidity / sqrtPX96 +- amount).\n /// @param sqrtPX96 The starting price, i.e. before accounting for the token0 delta\n /// @param liquidity The amount of usable liquidity\n /// @param amount How much of token0 to add or remove from virtual reserves\n /// @param add Whether to add or remove the amount of token0\n /// @return The price after adding or removing amount, depending on add\n function getNextSqrtPriceFromAmount0RoundingUp(\n uint160 sqrtPX96,\n uint128 liquidity,\n uint256 amount,\n bool add\n ) internal pure returns (uint160) {\n // we short circuit amount == 0 because the result is otherwise not guaranteed to equal the input price\n if (amount == 0) return sqrtPX96;\n uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\n\n if (add) {\n unchecked {\n uint256 product;\n if ((product = amount * sqrtPX96) / amount == sqrtPX96) {\n uint256 denominator = numerator1 + product;\n if (denominator >= numerator1)\n // always fits in 160 bits\n return uint160(FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator));\n }\n }\n // denominator is checked for overflow\n return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96) + amount));\n } else {\n unchecked {\n uint256 product;\n // if the product overflows, we know the denominator underflows\n // in addition, we must check that the denominator does not underflow\n require((product = amount * sqrtPX96) / amount == sqrtPX96 && numerator1 > product);\n uint256 denominator = numerator1 - product;\n return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator).toUint160();\n }\n }\n }\n\n /// @notice Gets the next sqrt price given a delta of token1\n /// @dev Always rounds down, because in the exact output case (decreasing price) we need to move the price at least\n /// far enough to get the desired output amount, and in the exact input case (increasing price) we need to move the\n /// price less in order to not send too much output.\n /// The formula we compute is within <1 wei of the lossless version: sqrtPX96 +- amount / liquidity\n /// @param sqrtPX96 The starting price, i.e., before accounting for the token1 delta\n /// @param liquidity The amount of usable liquidity\n /// @param amount How much of token1 to add, or remove, from virtual reserves\n /// @param add Whether to add, or remove, the amount of token1\n /// @return The price after adding or removing `amount`\n function getNextSqrtPriceFromAmount1RoundingDown(\n uint160 sqrtPX96,\n uint128 liquidity,\n uint256 amount,\n bool add\n ) internal pure returns (uint160) {\n // if we're adding (subtracting), rounding down requires rounding the quotient down (up)\n // in both cases, avoid a mulDiv for most inputs\n if (add) {\n uint256 quotient = (\n amount <= type(uint160).max\n ? (amount << FixedPoint96.RESOLUTION) / liquidity\n : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\n );\n\n return (uint256(sqrtPX96) + quotient).toUint160();\n } else {\n uint256 quotient = (\n amount <= type(uint160).max\n ? UnsafeMath.divRoundingUp(amount << FixedPoint96.RESOLUTION, liquidity)\n : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity)\n );\n\n require(sqrtPX96 > quotient);\n // always fits 160 bits\n unchecked {\n return uint160(sqrtPX96 - quotient);\n }\n }\n }\n\n /// @notice Gets the next sqrt price given an input amount of token0 or token1\n /// @dev Throws if price or liquidity are 0, or if the next price is out of bounds\n /// @param sqrtPX96 The starting price, i.e., before accounting for the input amount\n /// @param liquidity The amount of usable liquidity\n /// @param amountIn How much of token0, or token1, is being swapped in\n /// @param zeroForOne Whether the amount in is token0 or token1\n /// @return sqrtQX96 The price after adding the input amount to token0 or token1\n function getNextSqrtPriceFromInput(\n uint160 sqrtPX96,\n uint128 liquidity,\n uint256 amountIn,\n bool zeroForOne\n ) internal pure returns (uint160 sqrtQX96) {\n require(sqrtPX96 > 0);\n require(liquidity > 0);\n\n // round to make sure that we don't pass the target price\n return\n zeroForOne\n ? getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true)\n : getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true);\n }\n\n /// @notice Gets the next sqrt price given an output amount of token0 or token1\n /// @dev Throws if price or liquidity are 0 or the next price is out of bounds\n /// @param sqrtPX96 The starting price before accounting for the output amount\n /// @param liquidity The amount of usable liquidity\n /// @param amountOut How much of token0, or token1, is being swapped out\n /// @param zeroForOne Whether the amount out is token0 or token1\n /// @return sqrtQX96 The price after removing the output amount of token0 or token1\n function getNextSqrtPriceFromOutput(\n uint160 sqrtPX96,\n uint128 liquidity,\n uint256 amountOut,\n bool zeroForOne\n ) internal pure returns (uint160 sqrtQX96) {\n require(sqrtPX96 > 0);\n require(liquidity > 0);\n\n // round to make sure that we pass the target price\n return\n zeroForOne\n ? getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false)\n : getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false);\n }\n\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 ) internal pure returns (uint256 amount0) {\n unchecked {\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\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 ) internal pure returns (uint256 amount1) {\n unchecked {\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\n /// @notice Helper that gets signed token0 delta\n /// @param sqrtRatioAX96 A sqrt price\n /// @param sqrtRatioBX96 Another sqrt price\n /// @param liquidity The change in liquidity for which to compute the amount0 delta\n /// @return amount0 Amount of token0 corresponding to the passed liquidityDelta between the two prices\n function getAmount0Delta(\n uint160 sqrtRatioAX96,\n uint160 sqrtRatioBX96,\n int128 liquidity\n ) internal pure returns (int256 amount0) {\n unchecked {\n return\n liquidity < 0\n ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\n : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\n }\n }\n\n /// @notice Helper that gets signed token1 delta\n /// @param sqrtRatioAX96 A sqrt price\n /// @param sqrtRatioBX96 Another sqrt price\n /// @param liquidity The change in liquidity for which to compute the amount1 delta\n /// @return amount1 Amount of token1 corresponding to the passed liquidityDelta between the two prices\n function getAmount1Delta(\n uint160 sqrtRatioAX96,\n uint160 sqrtRatioBX96,\n int128 liquidity\n ) internal pure returns (int256 amount1) {\n unchecked {\n return\n liquidity < 0\n ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\n : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\n }\n }\n}\n" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "@uniswap/v3-core-0.8-support/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" + }, + "@uniswap/v3-core-0.8-support/contracts/libraries/BitMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\n/// @title BitMath\n/// @dev This library provides functionality for computing bit properties of an unsigned integer\nlibrary BitMath {\n /// @notice Returns the index of the most significant bit of the number,\n /// where the least significant bit is at index 0 and the most significant bit is at index 255\n /// @dev The function satisfies the property:\n /// x >= 2**mostSignificantBit(x) and x < 2**(mostSignificantBit(x)+1)\n /// @param x the value for which to compute the most significant bit, must be greater than 0\n /// @return r the index of the most significant bit\n function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {\n require(x > 0);\n\n unchecked {\n if (x >= 0x100000000000000000000000000000000) {\n x >>= 128;\n r += 128;\n }\n if (x >= 0x10000000000000000) {\n x >>= 64;\n r += 64;\n }\n if (x >= 0x100000000) {\n x >>= 32;\n r += 32;\n }\n if (x >= 0x10000) {\n x >>= 16;\n r += 16;\n }\n if (x >= 0x100) {\n x >>= 8;\n r += 8;\n }\n if (x >= 0x10) {\n x >>= 4;\n r += 4;\n }\n if (x >= 0x4) {\n x >>= 2;\n r += 2;\n }\n if (x >= 0x2) r += 1;\n }\n }\n\n /// @notice Returns the index of the least significant bit of the number,\n /// where the least significant bit is at index 0 and the most significant bit is at index 255\n /// @dev The function satisfies the property:\n /// (x & 2**leastSignificantBit(x)) != 0 and (x & (2**(leastSignificantBit(x)) - 1)) == 0)\n /// @param x the value for which to compute the least significant bit, must be greater than 0\n /// @return r the index of the least significant bit\n function leastSignificantBit(uint256 x) internal pure returns (uint8 r) {\n require(x > 0);\n\n unchecked {\n r = 255;\n if (x & type(uint128).max > 0) {\n r -= 128;\n } else {\n x >>= 128;\n }\n if (x & type(uint64).max > 0) {\n r -= 64;\n } else {\n x >>= 64;\n }\n if (x & type(uint32).max > 0) {\n r -= 32;\n } else {\n x >>= 32;\n }\n if (x & type(uint16).max > 0) {\n r -= 16;\n } else {\n x >>= 16;\n }\n if (x & type(uint8).max > 0) {\n r -= 8;\n } else {\n x >>= 8;\n }\n if (x & 0xf > 0) {\n r -= 4;\n } else {\n x >>= 4;\n }\n if (x & 0x3 > 0) {\n r -= 2;\n } else {\n x >>= 2;\n }\n if (x & 0x1 > 0) r -= 1;\n }\n }\n}\n" + }, + "contracts/libraries/Bisection.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\n\n/// @title Bisection Method\n/// @notice https://en.wikipedia.org/wiki/Bisection_method\nlibrary Bisection {\n error SolutionOutOfBounds(uint256 y_target, uint160 x_lower, uint160 x_upper);\n\n /// @notice Finds the solution to the equation f(x) = y_target using the bisection method\n /// @param f: strictly increasing function f: uint160 -> uint256\n /// @param y_target: the target value of f(x)\n /// @param x_lower: the lower bound for x\n /// @param x_upper: the upper bound for x\n /// @return x_target: the rounded down solution to the equation f(x) = y_target\n function findSolution(\n function(uint160) pure returns (uint256) f,\n uint256 y_target,\n uint160 x_lower,\n uint160 x_upper\n ) internal pure returns (uint160) {\n // compute y at the bounds\n uint256 y_lower = f(x_lower);\n uint256 y_upper = f(x_upper);\n\n // if y is out of the bounds then revert\n if (y_target < y_lower || y_target > y_upper) revert SolutionOutOfBounds(y_target, x_lower, x_upper);\n\n // bisect repeatedly until the solution is within an error of 1 unit\n uint256 y_mid;\n uint160 x_mid;\n while (x_upper - x_lower > 1) {\n x_mid = x_lower + (x_upper - x_lower) / 2;\n y_mid = f(x_mid);\n if (y_mid > y_target) {\n x_upper = x_mid;\n y_upper = y_mid;\n } else {\n x_lower = x_mid;\n y_lower = y_mid;\n }\n }\n\n // at this point, x_upper - x_lower is either 0 or 1\n // if it is 1 then check if x_upper is the solution, else return x_lower as the rounded down solution\n return x_lower != x_upper && f(x_upper) == y_target ? x_upper : x_lower;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() initializer {}\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\n // contract may have been reentered.\n require(_initializing ? _isConstructor() : !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} modifier, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "contracts/libraries/AddressHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { IVToken } from '../interfaces/IVToken.sol';\n\n/// @title Address helper functions\nlibrary AddressHelper {\n /// @notice converts address to uint32, using the least significant 32 bits\n /// @param addr Address to convert\n /// @return truncated last 4 bytes of the address\n function truncate(address addr) internal pure returns (uint32 truncated) {\n assembly {\n truncated := and(addr, 0xffffffff)\n }\n }\n\n /// @notice converts IERC20 contract to uint32\n /// @param addr contract\n /// @return truncated last 4 bytes of the address\n function truncate(IERC20 addr) internal pure returns (uint32 truncated) {\n return truncate(address(addr));\n }\n\n /// @notice checks if two addresses are equal\n /// @param a first address\n /// @param b second address\n /// @return true if addresses are equal\n function eq(address a, address b) internal pure returns (bool) {\n return a == b;\n }\n\n /// @notice checks if addresses of two IERC20 contracts are equal\n /// @param a first contract\n /// @param b second contract\n /// @return true if addresses are equal\n function eq(IERC20 a, IERC20 b) internal pure returns (bool) {\n return eq(address(a), address(b));\n }\n\n /// @notice checks if an address is zero\n /// @param a address to check\n /// @return true if address is zero\n function isZero(address a) internal pure returns (bool) {\n return a == address(0);\n }\n\n /// @notice checks if address of an IERC20 contract is zero\n /// @param a contract to check\n /// @return true if address is zero\n function isZero(IERC20 a) internal pure returns (bool) {\n return isZero(address(a));\n }\n}\n" + }, + "contracts/libraries/TickExtended.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { FundingPayment } from './FundingPayment.sol';\n\nimport { IVToken } from '../interfaces/IVToken.sol';\n\n/// @title Extended tick state for VPoolWrapper\nlibrary TickExtended {\n struct Info {\n int256 sumALastX128;\n int256 sumBOutsideX128;\n int256 sumFpOutsideX128;\n uint256 sumFeeOutsideX128;\n }\n\n /// @notice Calculates the extended tick state inside a tick range\n /// @param self mapping of tick index to tick extended state\n /// @param tickLower lower tick index\n /// @param tickUpper upper tick index\n /// @param tickCurrent current tick index\n /// @param fpGlobal global funding payment state\n /// @param sumFeeGlobalX128 global sum of fees for liquidity providers\n /// @return sumBInsideX128 sum of all B values for trades that took place inside the tick range\n /// @return sumFpInsideX128 sum of all FP values for trades that took place inside the tick range\n /// @return sumFeeInsideX128 sum of all fee values for trades that took place inside the tick range\n function getTickExtendedStateInside(\n mapping(int24 => TickExtended.Info) storage self,\n int24 tickLower,\n int24 tickUpper,\n int24 tickCurrent,\n FundingPayment.Info memory fpGlobal,\n uint256 sumFeeGlobalX128\n )\n internal\n view\n returns (\n int256 sumBInsideX128,\n int256 sumFpInsideX128,\n uint256 sumFeeInsideX128\n )\n {\n Info storage lower = self[tickLower];\n Info storage upper = self[tickUpper];\n\n int256 sumBBelowX128 = lower.sumBOutsideX128;\n int256 sumFpBelowX128 = FundingPayment.extrapolatedSumFpX128(\n lower.sumALastX128,\n sumBBelowX128, // lower.sumBOutsideX128,\n lower.sumFpOutsideX128,\n fpGlobal.sumAX128\n );\n uint256 sumFeeBelowX128 = lower.sumFeeOutsideX128;\n if (tickLower > tickCurrent) {\n sumBBelowX128 = fpGlobal.sumBX128 - sumBBelowX128;\n sumFpBelowX128 = fpGlobal.sumFpX128 - sumFpBelowX128;\n sumFeeBelowX128 = sumFeeGlobalX128 - sumFeeBelowX128;\n }\n\n int256 sumBAboveX128 = upper.sumBOutsideX128;\n int256 sumFpAboveX128 = FundingPayment.extrapolatedSumFpX128(\n upper.sumALastX128,\n sumBAboveX128, // upper.sumBOutsideX128,\n upper.sumFpOutsideX128,\n fpGlobal.sumAX128\n );\n uint256 sumFeeAboveX128 = upper.sumFeeOutsideX128;\n if (tickUpper <= tickCurrent) {\n sumBAboveX128 = fpGlobal.sumBX128 - sumBAboveX128;\n sumFpAboveX128 = fpGlobal.sumFpX128 - sumFpAboveX128;\n sumFeeAboveX128 = sumFeeGlobalX128 - sumFeeAboveX128;\n }\n\n sumBInsideX128 = fpGlobal.sumBX128 - sumBBelowX128 - sumBAboveX128;\n sumFpInsideX128 = fpGlobal.sumFpX128 - sumFpBelowX128 - sumFpAboveX128;\n sumFeeInsideX128 = sumFeeGlobalX128 - sumFeeBelowX128 - sumFeeAboveX128;\n }\n\n /// @notice Updates the extended tick state whenever liquidity is updated\n /// @param self mapping of tick index to tick extended state\n /// @param tick to update\n /// @param tickCurrent current tick index\n /// @param liquidityDelta delta of liquidity\n /// @param sumAGlobalX128 global funding payment state sumA\n /// @param sumBGlobalX128 global funding payment state sumB\n /// @param sumFpGlobalX128 global funding payment state sumFp\n /// @param sumFeeGlobalX128 global sum of fees for liquidity providers\n /// @param vPool uniswap v3 pool contract\n /// @return flipped whether the tick was flipped or no\n function update(\n mapping(int24 => TickExtended.Info) storage self,\n int24 tick,\n int24 tickCurrent,\n int128 liquidityDelta,\n int256 sumAGlobalX128,\n int256 sumBGlobalX128,\n int256 sumFpGlobalX128,\n uint256 sumFeeGlobalX128,\n IUniswapV3Pool vPool\n ) internal returns (bool flipped) {\n TickExtended.Info storage info = self[tick];\n\n (uint128 liquidityGrossBefore, , , , , , , ) = vPool.ticks(tick);\n uint128 liquidityGrossAfter = liquidityDelta < 0\n ? liquidityGrossBefore - uint128(-liquidityDelta)\n : liquidityGrossBefore + uint128(liquidityDelta);\n\n flipped = (liquidityGrossAfter == 0) != (liquidityGrossBefore == 0);\n\n if (liquidityGrossBefore == 0) {\n // by convention, we assume that all growth before a tick was initialized happened _below_ the tick\n if (tick <= tickCurrent) {\n info.sumALastX128 = sumAGlobalX128;\n info.sumBOutsideX128 = sumBGlobalX128;\n info.sumFpOutsideX128 = sumFpGlobalX128;\n info.sumFeeOutsideX128 = sumFeeGlobalX128;\n }\n }\n }\n\n /// @notice Updates the extended tick state whenever tick is crossed in a swap\n /// @param self mapping of tick index to tick extended state\n /// @param tick to update\n /// @param fpGlobal global funding payment state\n /// @param sumFeeGlobalX128 global sum of fees for liquidity providers\n function cross(\n mapping(int24 => TickExtended.Info) storage self,\n int24 tick,\n FundingPayment.Info memory fpGlobal,\n uint256 sumFeeGlobalX128\n ) internal {\n TickExtended.Info storage info = self[tick];\n int256 sumFpOutsideX128 = FundingPayment.extrapolatedSumFpX128(\n info.sumALastX128,\n info.sumBOutsideX128,\n info.sumFpOutsideX128,\n fpGlobal.sumAX128\n );\n info.sumALastX128 = fpGlobal.sumAX128;\n info.sumBOutsideX128 = fpGlobal.sumBX128 - info.sumBOutsideX128;\n info.sumFpOutsideX128 = fpGlobal.sumFpX128 - sumFpOutsideX128;\n info.sumFeeOutsideX128 = sumFeeGlobalX128 - info.sumFeeOutsideX128;\n }\n\n /// @notice Clears tick data\n /// @param self The mapping containing all initialized tick information for initialized ticks\n /// @param tick The tick that will be cleared\n function clear(mapping(int24 => TickExtended.Info) storage self, int24 tick) internal {\n delete self[tick];\n }\n}\n" + }, + "contracts/libraries/SwapMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { SignedMath } from './SignedMath.sol';\n\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\n\n/// @title Swap computation functions\nlibrary SwapMath {\n using SignedMath for int256;\n\n /// @notice Executed before swap call to uniswap, to inflate the swap result values\n /// @param exactIn Whether user specified in amount or out amount\n /// @param swapVTokenForVQuote swap direction\n /// @param uniswapFeePips fee ratio that will be collected by uniswap\n /// @param liquidityFeePips fee ratio to be applied in rage trade for paying to liquidity providers\n /// @param protocolFeePips fee ratio to be applied in rage trade for protocol treasury\n /// @param swapResult pointer to the swap result struct\n /// @dev this method mutates the data pointed by swapResult\n function beforeSwap(\n bool exactIn,\n bool swapVTokenForVQuote,\n uint24 uniswapFeePips,\n uint24 liquidityFeePips,\n uint24 protocolFeePips,\n IVPoolWrapper.SwapResult memory swapResult\n ) internal pure {\n // inflate or deinfate to undo uniswap fees if necessary, and account for our fees\n if (exactIn) {\n if (swapVTokenForVQuote) {\n // CASE: exactIn vToken\n // fee: not now, will collect fee in vQuote after swap\n // inflate: for undoing the uniswap fees\n swapResult.amountSpecified = inflate(swapResult.amountSpecified, uniswapFeePips);\n } else {\n // CASE: exactIn vQuote\n // fee: remove fee and do smaller swap, so trader gets less vTokens\n // here, amountSpecified == swap amount + fee\n (swapResult.liquidityFees, swapResult.protocolFees) = calculateFees(\n swapResult.amountSpecified,\n AmountTypeEnum.VQUOTE_AMOUNT_PLUS_FEES,\n liquidityFeePips,\n protocolFeePips\n );\n swapResult.amountSpecified = includeFees(\n swapResult.amountSpecified,\n swapResult.liquidityFees + swapResult.protocolFees,\n IncludeFeeEnum.SUBTRACT_FEE\n );\n // inflate: uniswap will collect fee so inflate to undo it\n swapResult.amountSpecified = inflate(swapResult.amountSpecified, uniswapFeePips);\n }\n } else {\n if (!swapVTokenForVQuote) {\n // CASE: exactOut vToken\n // fee: no need to collect fee as we want to collect fee in vQuote later\n // inflate: no need to inflate as uniswap collects fees in tokenIn\n } else {\n // CASE: exactOut vQuote\n // fee: buy more vQuote (short more vToken) so that fee can be removed in vQuote\n // here, amountSpecified + fee == swap amount\n (swapResult.liquidityFees, swapResult.protocolFees) = calculateFees(\n swapResult.amountSpecified,\n AmountTypeEnum.VQUOTE_AMOUNT_MINUS_FEES,\n liquidityFeePips,\n protocolFeePips\n );\n swapResult.amountSpecified = includeFees(\n swapResult.amountSpecified,\n swapResult.liquidityFees + swapResult.protocolFees,\n IncludeFeeEnum.ADD_FEE\n );\n }\n }\n }\n\n /// @notice Executed after swap call to uniswap, to deinflate the swap result values\n /// @param exactIn Whether user specified in amount or out amount\n /// @param swapVTokenForVQuote swap direction\n /// @param uniswapFeePips fee that will be collected by uniswap\n /// @param liquidityFeePips fee ratio to be applied in rage trade for paying to liquidity providers\n /// @param protocolFeePips fee ratio to be applied in rage trade for protocol treasury\n /// @param swapResult pointer to the swap result struct\n /// @dev This method mutates the data pointed by swapResult\n function afterSwap(\n bool exactIn,\n bool swapVTokenForVQuote,\n uint24 uniswapFeePips,\n uint24 liquidityFeePips,\n uint24 protocolFeePips,\n IVPoolWrapper.SwapResult memory swapResult\n ) internal pure {\n // swap is done so now adjusting vTokenIn and vQuoteIn amounts to remove uniswap fees and add our fees\n if (exactIn) {\n if (swapVTokenForVQuote) {\n // CASE: exactIn vToken\n // deinflate: vToken amount was inflated so that uniswap can collect fee\n swapResult.vTokenIn = deinflate(swapResult.vTokenIn, uniswapFeePips);\n\n // fee: collect the fee, give less vQuote to trader\n // here, vQuoteIn == swap amount\n (swapResult.liquidityFees, swapResult.protocolFees) = calculateFees(\n swapResult.vQuoteIn,\n AmountTypeEnum.ZERO_FEE_VQUOTE_AMOUNT,\n liquidityFeePips,\n protocolFeePips\n );\n swapResult.vQuoteIn = includeFees(\n swapResult.vQuoteIn,\n swapResult.liquidityFees + swapResult.protocolFees,\n IncludeFeeEnum.SUBTRACT_FEE\n );\n } else {\n // CASE: exactIn vQuote\n // deinflate: vQuote amount was inflated, hence need to deinflate for generating final statement\n swapResult.vQuoteIn = deinflate(swapResult.vQuoteIn, uniswapFeePips);\n // fee: fee is already removed before swap, lets include it to the final bill, so that trader pays for it\n swapResult.vQuoteIn = includeFees(\n swapResult.vQuoteIn,\n swapResult.liquidityFees + swapResult.protocolFees,\n IncludeFeeEnum.ADD_FEE\n );\n }\n } else {\n if (!swapVTokenForVQuote) {\n // CASE: exactOut vToken\n // deinflate: uniswap want to collect fee in vQuote and hence ask more, so need to deinflate it\n swapResult.vQuoteIn = deinflate(swapResult.vQuoteIn, uniswapFeePips);\n // fee: collecting fees in vQuote\n // here, vQuoteIn == swap amount\n (swapResult.liquidityFees, swapResult.protocolFees) = calculateFees(\n swapResult.vQuoteIn,\n AmountTypeEnum.ZERO_FEE_VQUOTE_AMOUNT,\n liquidityFeePips,\n protocolFeePips\n );\n swapResult.vQuoteIn = includeFees(\n swapResult.vQuoteIn,\n swapResult.liquidityFees + swapResult.protocolFees,\n IncludeFeeEnum.ADD_FEE\n );\n } else {\n // CASE: exactOut vQuote\n // deinflate: uniswap want to collect fee in vToken and hence ask more, so need to deinflate it\n swapResult.vTokenIn = deinflate(swapResult.vTokenIn, uniswapFeePips);\n // fee: already calculated before, subtract now\n swapResult.vQuoteIn = includeFees(\n swapResult.vQuoteIn,\n swapResult.liquidityFees + swapResult.protocolFees,\n IncludeFeeEnum.SUBTRACT_FEE\n );\n }\n }\n }\n\n /// @notice Inflates the amount such that when uniswap collects the fee, it will get the same amount\n /// @param amount user specified amount\n /// @param uniswapFeePips fee that will be collected by uniswap\n /// @return inflated amount, on which applying uniswap fee gives the user specifed amount\n function inflate(int256 amount, uint24 uniswapFeePips) internal pure returns (int256 inflated) {\n int256 fees = (amount * int256(uint256(uniswapFeePips))) / int24(1e6 - uniswapFeePips) + 1; // round up\n inflated = amount + fees;\n }\n\n /// @notice Undoes the inflation of the amount\n /// @param inflated amount from uniswap after the swap call\n /// @param uniswapFeePips fee that will be collected by uniswap\n /// @return amount that is deinflated, which can be given to user\n function deinflate(int256 inflated, uint24 uniswapFeePips) internal pure returns (int256 amount) {\n amount = (inflated * int24(1e6 - uniswapFeePips)) / 1e6;\n }\n\n enum AmountTypeEnum {\n ZERO_FEE_VQUOTE_AMOUNT,\n VQUOTE_AMOUNT_MINUS_FEES,\n VQUOTE_AMOUNT_PLUS_FEES\n }\n\n /// @notice Calculates the fees to be collected by rage trade protocol\n /// @param amount should be in vQuote denomination, since fees to be collected only in vQuote\n /// @param amountTypeEnum type of amount\n /// @param liquidityFeePips fee ratio to be applied in rage trade for paying to liquidity providers\n /// @param protocolFeePips fee ratio to be applied in rage trade for protocol treasury\n /// @return liquidityFees calculated fees in vQuote, to be given to liquidity providers\n /// @return protocolFees calculated fees in vQuote, to be given to protocol treasury\n function calculateFees(\n int256 amount,\n AmountTypeEnum amountTypeEnum,\n uint24 liquidityFeePips,\n uint24 protocolFeePips\n ) internal pure returns (uint256 liquidityFees, uint256 protocolFees) {\n uint256 amountAbs = uint256(amount.abs());\n if (amountTypeEnum == AmountTypeEnum.VQUOTE_AMOUNT_MINUS_FEES) {\n // when amount is already subtracted by fees, we need to scale it up, so that\n // on calculating and subtracting fees on the scaled up value, we should get same amount\n amountAbs = (amountAbs * 1e6) / uint256(1e6 - liquidityFeePips - protocolFeePips);\n } else if (amountTypeEnum == AmountTypeEnum.VQUOTE_AMOUNT_PLUS_FEES) {\n // when amount is already added with fees, we need to scale it down, so that\n // on calculating and adding fees on the scaled down value, we should get same amount\n amountAbs = (amountAbs * 1e6) / uint256(1e6 + liquidityFeePips + protocolFeePips);\n }\n uint256 fees = (amountAbs * (liquidityFeePips + protocolFeePips)) / 1e6 + 1; // round up\n liquidityFees = (amountAbs * liquidityFeePips) / 1e6 + 1; // round up\n protocolFees = fees - liquidityFees;\n }\n\n enum IncludeFeeEnum {\n ADD_FEE,\n SUBTRACT_FEE\n }\n\n /// @notice Applies the fees in the amount, based on sign of the amount\n /// @param amount amount to which fees are to be applied\n /// @param fees fees to be applied\n /// @param includeFeeEnum procedure to apply the fee\n /// @return amountAfterFees amount after applying fees\n function includeFees(\n int256 amount,\n uint256 fees,\n IncludeFeeEnum includeFeeEnum\n ) internal pure returns (int256 amountAfterFees) {\n if ((amount > 0) == (includeFeeEnum == IncludeFeeEnum.ADD_FEE)) {\n amountAfterFees = amount + int256(fees);\n } else {\n amountAfterFees = amount - int256(fees);\n }\n }\n}\n" + }, + "contracts/utils/Extsload.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport { IExtsload } from '../interfaces/IExtsload.sol';\n\n/// @notice Allows the inheriting contract make it's state accessable to other contracts\n/// https://ethereum-magicians.org/t/extsload-opcode-proposal/2410/11\nabstract contract Extsload is IExtsload {\n function extsload(bytes32 slot) external view returns (bytes32 val) {\n assembly {\n val := sload(slot)\n }\n }\n\n function extsload(bytes32[] memory slots) external view returns (bytes32[] memory) {\n assembly {\n let end := add(0x20, add(slots, mul(mload(slots), 0x20)))\n for {\n let pointer := add(slots, 32)\n } lt(pointer, end) {\n\n } {\n let value := sload(mload(pointer))\n mstore(pointer, value)\n pointer := add(pointer, 0x20)\n }\n }\n\n return slots;\n }\n}\n" + }, + "contracts/utils/constants.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\n// Uniswap V3 Factory address is same across different networks\naddress constant UNISWAP_V3_FACTORY_ADDRESS = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\nuint24 constant UNISWAP_V3_DEFAULT_FEE_TIER = 500;\nint24 constant UNISWAP_V3_DEFAULT_TICKSPACING = 10;\nbytes32 constant UNISWAP_V3_POOL_BYTE_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "contracts/test/mocks/VPoolWrapperMock2.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { VPoolWrapper } from '../../protocol/wrapper/VPoolWrapper.sol';\nimport { SwapMath } from '../../libraries/SwapMath.sol';\n\ncontract VPoolWrapperMock2 is VPoolWrapper {\n uint48 public blockTimestamp;\n\n constructor() {\n blockTimestamp = uint48(block.timestamp);\n }\n\n function _blockTimestamp() internal view override returns (uint48) {\n // constructor of VPoolWrapper runs first, there _blockTimestamp() returns zero\n if (blockTimestamp == 0) return uint48(block.timestamp);\n else return blockTimestamp;\n }\n\n function increaseTimestamp(uint48 secs) external {\n blockTimestamp += secs;\n }\n\n function calculateFees(int256 amount, SwapMath.AmountTypeEnum amountTypeEnum)\n public\n view\n returns (uint256 liquidityFees, uint256 protocolFees)\n {\n return SwapMath.calculateFees(amount, amountTypeEnum, liquidityFeePips, protocolFeePips);\n }\n}\n" + }, + "contracts/test/LiquidityPositionTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { LiquidityPosition } from '../libraries/LiquidityPosition.sol';\nimport { Account } from '../libraries/Account.sol';\nimport { VPoolWrapperMock } from './mocks/VPoolWrapperMock.sol';\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\n\nimport { AccountProtocolInfoMock } from './mocks/AccountProtocolInfoMock.sol';\n\ncontract LiquidityPositionTest is AccountProtocolInfoMock {\n using LiquidityPosition for LiquidityPosition.Info;\n\n IClearingHouseStructures.BalanceAdjustments public balanceAdjustments;\n LiquidityPosition.Info public lp;\n VPoolWrapperMock public wrapper;\n\n constructor() {\n wrapper = new VPoolWrapperMock();\n }\n\n function initialize(int24 tickLower, int24 tickUpper) external {\n lp.initialize(tickLower, tickUpper);\n }\n\n function updateCheckpoints() external {\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside = wrapper.getValuesInside(\n lp.tickLower,\n lp.tickUpper\n );\n lp.update(0, 0, wrapperValuesInside, balanceAdjustments);\n }\n\n function netPosition(uint160 sqrtPriceCurrent) public view returns (int256) {\n return lp.netPosition(sqrtPriceCurrent);\n }\n\n function liquidityChange(int128 liquidity) public {\n protocol.pools[0].vPoolWrapper = wrapper;\n protocol.pools[0].vPool = wrapper.vPool();\n lp.liquidityChange(0, 0, liquidity, balanceAdjustments, protocol);\n }\n\n function maxNetPosition() public view returns (uint256) {\n return lp.maxNetPosition();\n }\n\n function marketValue(uint160 sqrtPriceCurrent) public view returns (int256) {\n return lp.marketValue(sqrtPriceCurrent, wrapper);\n }\n}\n" + }, + "contracts/libraries/LiquidityPosition.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.4;\n\nimport { SqrtPriceMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/SqrtPriceMath.sol';\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\nimport { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';\n\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { PriceMath } from './PriceMath.sol';\nimport { Protocol } from './Protocol.sol';\nimport { SignedFullMath } from './SignedFullMath.sol';\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\nimport { FundingPayment } from './FundingPayment.sol';\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\n\n/// @title Liquidity position functions\nlibrary LiquidityPosition {\n using FullMath for uint256;\n using PriceMath for uint160;\n using SafeCast for uint256;\n using SignedFullMath for int256;\n using UniswapV3PoolHelper for IUniswapV3Pool;\n\n using LiquidityPosition for LiquidityPosition.Info;\n using Protocol for Protocol.Info;\n\n struct Set {\n // multiple per pool because it's non-fungible, allows for 4 billion LP positions lifetime\n uint48[5] active;\n // concat(tickLow,tickHigh)\n mapping(uint48 => LiquidityPosition.Info) positions;\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\n }\n\n struct Info {\n //Extra boolean to check if it is limit order and uint to track limit price.\n IClearingHouseEnums.LimitOrderType limitOrderType;\n // the tick range of the position;\n int24 tickLower;\n int24 tickUpper;\n // the liquidity of the position\n uint128 liquidity;\n int256 vTokenAmountIn;\n // funding payment checkpoints\n int256 sumALastX128;\n int256 sumBInsideLastX128;\n int256 sumFpInsideLastX128;\n // fee growth inside\n uint256 sumFeeInsideLastX128;\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\n }\n\n error LP_AlreadyInitialized();\n error LP_IneligibleLimitOrderRemoval();\n\n /// @notice denotes liquidity add/remove\n /// @param accountId serial number of the account\n /// @param poolId address of token whose position was taken\n /// @param tickLower lower tick of the range updated\n /// @param tickUpper upper tick of the range updated\n /// @param liquidityDelta change in liquidity value\n /// @param limitOrderType the type of range position\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\n /// @param vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\n event LiquidityChanged(\n uint256 indexed accountId,\n uint32 indexed poolId,\n int24 tickLower,\n int24 tickUpper,\n int128 liquidityDelta,\n IClearingHouseEnums.LimitOrderType limitOrderType,\n int256 vTokenAmountOut,\n int256 vQuoteAmountOut,\n uint160 sqrtPriceX96\n );\n\n /// @param accountId serial number of the account\n /// @param poolId address of token for which funding was paid\n /// @param tickLower lower tick of the range for which funding was paid\n /// @param tickUpper upper tick of the range for which funding was paid\n /// @param amount amount of funding paid (negative) or received (positive)\n /// @param sumALastX128 val of sum of the term A in funding payment math, when op took place\n /// @param sumBInsideLastX128 val of sum of the term B in funding payment math, when op took place\n /// @param sumFpInsideLastX128 val of sum of the term Fp in funding payment math, when op took place\n /// @param sumFeeInsideLastX128 val of sum of the term Fee in wrapper, when op took place\n event LiquidityPositionFundingPaymentRealized(\n uint256 indexed accountId,\n uint32 indexed poolId,\n int24 tickLower,\n int24 tickUpper,\n int256 amount,\n int256 sumALastX128,\n int256 sumBInsideLastX128,\n int256 sumFpInsideLastX128,\n uint256 sumFeeInsideLastX128\n );\n\n /// @notice denotes fee payment for a range / token position\n /// @dev for a token position tickLower = tickUpper = 0\n /// @param accountId serial number of the account\n /// @param poolId address of token for which fee was paid\n /// @param tickLower lower tick of the range for which fee was paid\n /// @param tickUpper upper tick of the range for which fee was paid\n /// @param amount amount of fee paid (negative) or received (positive)\n event LiquidityPositionEarningsRealized(\n uint256 indexed accountId,\n uint32 indexed poolId,\n int24 tickLower,\n int24 tickUpper,\n int256 amount\n );\n\n /**\n * Internal methods\n */\n\n /// @notice initializes a new LiquidityPosition.Info struct\n /// @dev Reverts if the position is already initialized\n /// @param position storage pointer of the position to initialize\n /// @param tickLower lower tick of the range\n /// @param tickUpper upper tick of the range\n function initialize(\n LiquidityPosition.Info storage position,\n int24 tickLower,\n int24 tickUpper\n ) internal {\n if (position.isInitialized()) {\n revert LP_AlreadyInitialized();\n }\n\n position.tickLower = tickLower;\n position.tickUpper = tickUpper;\n }\n\n /// @notice changes liquidity for a position, informs pool wrapper and does necessary bookkeeping\n /// @param position storage ref of the position to update\n /// @param accountId serial number of the account, used to emit event\n /// @param poolId id of the pool for which position was updated\n /// @param liquidityDelta change in liquidity value\n /// @param balanceAdjustments memory ref to the balance adjustments struct\n /// @param protocol ref to the protocol state\n function liquidityChange(\n LiquidityPosition.Info storage position,\n uint256 accountId,\n uint32 poolId,\n int128 liquidityDelta,\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\n Protocol.Info storage protocol\n ) internal {\n int256 vTokenPrincipal;\n int256 vQuotePrincipal;\n\n IVPoolWrapper wrapper = protocol.vPoolWrapper(poolId);\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside;\n\n // calls wrapper to mint/burn liquidity\n if (liquidityDelta > 0) {\n uint256 vTokenPrincipal_;\n uint256 vQuotePrincipal_;\n (vTokenPrincipal_, vQuotePrincipal_, wrapperValuesInside) = wrapper.mint(\n position.tickLower,\n position.tickUpper,\n uint128(liquidityDelta)\n );\n vTokenPrincipal = vTokenPrincipal_.toInt256();\n vQuotePrincipal = vQuotePrincipal_.toInt256();\n } else {\n uint256 vTokenPrincipal_;\n uint256 vQuotePrincipal_;\n (vTokenPrincipal_, vQuotePrincipal_, wrapperValuesInside) = wrapper.burn(\n position.tickLower,\n position.tickUpper,\n uint128(-liquidityDelta)\n );\n vTokenPrincipal = -vTokenPrincipal_.toInt256();\n vQuotePrincipal = -vQuotePrincipal_.toInt256();\n }\n\n // calculate funding payment and liquidity fees then update checkpoints\n position.update(accountId, poolId, wrapperValuesInside, balanceAdjustments);\n\n // adjust in the token acounts\n balanceAdjustments.vQuoteIncrease -= vQuotePrincipal;\n balanceAdjustments.vTokenIncrease -= vTokenPrincipal;\n\n // emit the event\n uint160 sqrtPriceCurrent = protocol.vPool(poolId).sqrtPriceCurrent();\n emitLiquidityChangeEvent(\n position,\n accountId,\n poolId,\n liquidityDelta,\n sqrtPriceCurrent,\n -vTokenPrincipal,\n -vQuotePrincipal\n );\n\n // update trader position increase\n int256 vTokenAmountCurrent;\n {\n (vTokenAmountCurrent, ) = position.vTokenAmountsInRange(sqrtPriceCurrent, false);\n balanceAdjustments.traderPositionIncrease += (vTokenAmountCurrent - position.vTokenAmountIn);\n }\n\n uint128 liquidityNew = position.liquidity;\n if (liquidityDelta > 0) {\n liquidityNew += uint128(liquidityDelta);\n } else if (liquidityDelta < 0) {\n liquidityNew -= uint128(-liquidityDelta);\n }\n\n if (liquidityNew != 0) {\n // update state\n position.liquidity = liquidityNew;\n position.vTokenAmountIn = vTokenAmountCurrent + vTokenPrincipal;\n } else {\n // clear all the state\n position.liquidity = 0;\n position.vTokenAmountIn = 0;\n position.sumALastX128 = 0;\n position.sumBInsideLastX128 = 0;\n position.sumFpInsideLastX128 = 0;\n position.sumFeeInsideLastX128 = 0;\n }\n }\n\n /// @notice updates the position with latest checkpoints, and realises fees and fp\n /// @dev fees and funding payment are not immediately adjusted in token balance state,\n /// balanceAdjustments struct is used to pass the necessary values to caller.\n /// @param position storage ref of the position to update\n /// @param accountId serial number of the account, used to emit event\n /// @param poolId id of the pool for which position was updated\n /// @param wrapperValuesInside range checkpoint values from the wrapper\n /// @param balanceAdjustments memory ref to the balance adjustments struct\n function update(\n LiquidityPosition.Info storage position,\n uint256 accountId,\n uint32 poolId,\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside,\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments\n ) internal {\n int256 fundingPayment = position.unrealizedFundingPayment(\n wrapperValuesInside.sumAX128,\n wrapperValuesInside.sumFpInsideX128\n );\n balanceAdjustments.vQuoteIncrease += fundingPayment;\n\n int256 unrealizedLiquidityFee = position.unrealizedFees(wrapperValuesInside.sumFeeInsideX128).toInt256();\n balanceAdjustments.vQuoteIncrease += unrealizedLiquidityFee;\n\n // updating checkpoints\n position.sumALastX128 = wrapperValuesInside.sumAX128;\n position.sumBInsideLastX128 = wrapperValuesInside.sumBInsideX128;\n position.sumFpInsideLastX128 = wrapperValuesInside.sumFpInsideX128;\n position.sumFeeInsideLastX128 = wrapperValuesInside.sumFeeInsideX128;\n\n emit LiquidityPositionFundingPaymentRealized(\n accountId,\n poolId,\n position.tickLower,\n position.tickUpper,\n fundingPayment,\n wrapperValuesInside.sumAX128,\n wrapperValuesInside.sumBInsideX128,\n wrapperValuesInside.sumFpInsideX128,\n wrapperValuesInside.sumFeeInsideX128\n );\n\n emit LiquidityPositionEarningsRealized(\n accountId,\n poolId,\n position.tickLower,\n position.tickUpper,\n unrealizedLiquidityFee\n );\n }\n\n /**\n * Internal view methods\n */\n\n /// @notice ensures that limit order removal is valid, else reverts\n /// @param info storage ref of the position to check\n /// @param currentTick current tick in the pool\n function checkValidLimitOrderRemoval(LiquidityPosition.Info storage info, int24 currentTick) internal view {\n if (\n !((currentTick >= info.tickUpper &&\n info.limitOrderType == IClearingHouseEnums.LimitOrderType.UPPER_LIMIT) ||\n (currentTick <= info.tickLower &&\n info.limitOrderType == IClearingHouseEnums.LimitOrderType.LOWER_LIMIT))\n ) {\n revert LP_IneligibleLimitOrderRemoval();\n }\n }\n\n /// @notice checks if the position is initialized\n /// @param info storage ref of the position to check\n /// @return true if the position is initialized\n function isInitialized(LiquidityPosition.Info storage info) internal view returns (bool) {\n return info.tickLower != 0 || info.tickUpper != 0;\n }\n\n /// @notice calculates the long side risk for the position\n /// @param position storage ref of the position to check\n /// @param valuationSqrtPriceX96 valuation sqrt price in x96\n /// @return long side risk\n function longSideRisk(LiquidityPosition.Info storage position, uint160 valuationSqrtPriceX96)\n internal\n view\n returns (uint256)\n {\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\n uint256 longPositionExecutionPriceX128;\n {\n uint160 sqrtPriceUpperMinX96 = valuationSqrtPriceX96 <= sqrtPriceUpperX96\n ? valuationSqrtPriceX96\n : sqrtPriceUpperX96;\n uint160 sqrtPriceLowerMinX96 = valuationSqrtPriceX96 <= sqrtPriceLowerX96\n ? valuationSqrtPriceX96\n : sqrtPriceLowerX96;\n longPositionExecutionPriceX128 = uint256(sqrtPriceLowerMinX96).mulDiv(sqrtPriceUpperMinX96, 1 << 64);\n }\n\n uint256 maxNetLongPosition;\n {\n uint256 maxLongTokens = SqrtPriceMath.getAmount0Delta(\n sqrtPriceLowerX96,\n sqrtPriceUpperX96,\n position.liquidity,\n true\n );\n //\n if (position.vTokenAmountIn >= 0) {\n //maxLongTokens in range should always be >= amount that got added to range, equality occurs when range was added at pCurrent = pHigh\n assert(maxLongTokens >= uint256(position.vTokenAmountIn));\n maxNetLongPosition = maxLongTokens - uint256(position.vTokenAmountIn);\n } else maxNetLongPosition = maxLongTokens + uint256(-1 * position.vTokenAmountIn);\n }\n\n return maxNetLongPosition.mulDiv(longPositionExecutionPriceX128, FixedPoint128.Q128);\n }\n\n /// @notice calculates the market value for the position using a provided price\n /// @param position storage ref of the position to check\n /// @param valuationSqrtPriceX96 valuation sqrt price to be used\n /// @param wrapper address of the pool wrapper\n /// @return marketValue_ the market value of the position\n function marketValue(\n LiquidityPosition.Info storage position,\n uint160 valuationSqrtPriceX96,\n IVPoolWrapper wrapper\n ) internal view returns (int256 marketValue_) {\n {\n (int256 vTokenAmount, int256 vQuoteAmount) = position.vTokenAmountsInRange(valuationSqrtPriceX96, false);\n uint256 priceX128 = valuationSqrtPriceX96.toPriceX128();\n marketValue_ = vTokenAmount.mulDiv(priceX128, FixedPoint128.Q128) + vQuoteAmount;\n }\n // adding fees\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside = wrapper.getExtrapolatedValuesInside(\n position.tickLower,\n position.tickUpper\n );\n marketValue_ += position.unrealizedFees(wrapperValuesInside.sumFeeInsideX128).toInt256();\n marketValue_ += position.unrealizedFundingPayment(\n wrapperValuesInside.sumAX128,\n wrapperValuesInside.sumFpInsideX128\n );\n }\n\n /// @notice calculates the max net position for the position\n /// @param position storage ref of the position to check\n /// @return maxNetPosition the max net position of the position\n function maxNetPosition(LiquidityPosition.Info storage position) internal view returns (uint256) {\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\n\n if (position.vTokenAmountIn >= 0)\n return\n SqrtPriceMath.getAmount0Delta(sqrtPriceLowerX96, sqrtPriceUpperX96, position.liquidity, true) -\n uint256(position.vTokenAmountIn);\n else\n return\n SqrtPriceMath.getAmount0Delta(sqrtPriceLowerX96, sqrtPriceUpperX96, position.liquidity, true) +\n uint256(-1 * position.vTokenAmountIn);\n }\n\n /// @notice calculates the current net position for the position\n /// @param position storage ref of the position to check\n /// @param sqrtPriceCurrent the current sqrt price, used to calculate net position\n /// @return netTokenPosition the current net position of the position\n function netPosition(LiquidityPosition.Info storage position, uint160 sqrtPriceCurrent)\n internal\n view\n returns (int256 netTokenPosition)\n {\n int256 vTokenAmountCurrent;\n (vTokenAmountCurrent, ) = position.vTokenAmountsInRange(sqrtPriceCurrent, false);\n netTokenPosition = (vTokenAmountCurrent - position.vTokenAmountIn);\n }\n\n /// @notice calculates the current virtual token amounts for the position\n /// @param position storage ref of the position to check\n /// @param sqrtPriceCurrent the current sqrt price, used to calculate virtual token amounts\n /// @param roundUp whether to round up the token amounts, purpose to charge user more and give less\n /// @return vTokenAmount the current vToken amount\n /// @return vQuoteAmount the current vQuote amount\n function vTokenAmountsInRange(\n LiquidityPosition.Info storage position,\n uint160 sqrtPriceCurrent,\n bool roundUp\n ) internal view returns (int256 vTokenAmount, int256 vQuoteAmount) {\n uint160 sqrtPriceLowerX96 = TickMath.getSqrtRatioAtTick(position.tickLower);\n uint160 sqrtPriceUpperX96 = TickMath.getSqrtRatioAtTick(position.tickUpper);\n\n // If price is outside the range, then consider it at the ends\n // for calculation of amounts\n uint160 sqrtPriceMiddleX96 = sqrtPriceCurrent;\n if (sqrtPriceCurrent < sqrtPriceLowerX96) {\n sqrtPriceMiddleX96 = sqrtPriceLowerX96;\n } else if (sqrtPriceCurrent > sqrtPriceUpperX96) {\n sqrtPriceMiddleX96 = sqrtPriceUpperX96;\n }\n\n vTokenAmount = SqrtPriceMath\n .getAmount0Delta(sqrtPriceMiddleX96, sqrtPriceUpperX96, position.liquidity, roundUp)\n .toInt256();\n vQuoteAmount = SqrtPriceMath\n .getAmount1Delta(sqrtPriceLowerX96, sqrtPriceMiddleX96, position.liquidity, roundUp)\n .toInt256();\n }\n\n /// @notice returns vQuoteIncrease due to unrealised funding payment for the liquidity position (+ve means receiving and -ve means giving)\n /// @param position storage ref of the position to check\n /// @param sumAX128 the sumA value from the pool wrapper\n /// @param sumFpInsideX128 the sumFp in the position's range from the pool wrapper\n /// @return vQuoteIncrease the amount of vQuote that should be added to the account's vQuote balance\n function unrealizedFundingPayment(\n LiquidityPosition.Info storage position,\n int256 sumAX128,\n int256 sumFpInsideX128\n ) internal view returns (int256 vQuoteIncrease) {\n // subtract the bill from the account's vQuote balance\n vQuoteIncrease = -FundingPayment.bill(\n sumAX128,\n sumFpInsideX128,\n position.sumALastX128,\n position.sumBInsideLastX128,\n position.sumFpInsideLastX128,\n position.liquidity\n );\n }\n\n /// @notice calculates the unrealised lp fees for the position\n /// @param position storage ref of the position to check\n /// @param sumFeeInsideX128 the global sumFee in the position's range from the pool wrapper\n /// @return vQuoteIncrease the amount of vQuote that should be added to the account's vQuote balance\n function unrealizedFees(LiquidityPosition.Info storage position, uint256 sumFeeInsideX128)\n internal\n view\n returns (uint256 vQuoteIncrease)\n {\n vQuoteIncrease = (sumFeeInsideX128 - position.sumFeeInsideLastX128).mulDiv(\n position.liquidity,\n FixedPoint128.Q128\n );\n }\n\n function emitLiquidityChangeEvent(\n LiquidityPosition.Info storage position,\n uint256 accountId,\n uint32 poolId,\n int128 liquidityDelta,\n uint160 sqrtPriceX96,\n int256 vTokenAmountOut,\n int256 vQuoteAmountOut\n ) internal {\n emit LiquidityChanged(\n accountId,\n poolId,\n position.tickLower,\n position.tickUpper,\n liquidityDelta,\n position.limitOrderType,\n vTokenAmountOut,\n vQuoteAmountOut,\n sqrtPriceX96\n );\n }\n}\n" + }, + "contracts/libraries/Account.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.4;\n\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\n\nimport { AddressHelper } from './AddressHelper.sol';\nimport { CollateralDeposit } from './CollateralDeposit.sol';\nimport { SignedFullMath } from './SignedFullMath.sol';\nimport { SignedMath } from './SignedMath.sol';\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\nimport { LiquidityPosition } from './LiquidityPosition.sol';\nimport { Protocol } from './Protocol.sol';\nimport { VTokenPosition } from './VTokenPosition.sol';\nimport { VTokenPositionSet } from './VTokenPositionSet.sol';\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\nimport { IVQuote } from '../interfaces/IVQuote.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\n/// @title Cross margined account functions\n/// @dev This library is deployed and used as an external library by ClearingHouse contract.\nlibrary Account {\n using AddressHelper for address;\n using FullMath for uint256;\n using SafeCast for uint256;\n using SignedFullMath for int256;\n using SignedMath for int256;\n\n using Account for Account.Info;\n using CollateralDeposit for CollateralDeposit.Set;\n using LiquidityPositionSet for LiquidityPosition.Set;\n using Protocol for Protocol.Info;\n using VTokenPosition for VTokenPosition.Info;\n using VTokenPositionSet for VTokenPosition.Set;\n\n /// @notice account info for user\n /// @param owner specifies the account owner\n /// @param tokenPositions is set of all open token positions\n /// @param collateralDeposits is set of all deposits\n struct Info {\n uint96 id;\n address owner;\n VTokenPosition.Set tokenPositions;\n CollateralDeposit.Set collateralDeposits;\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\n }\n\n /**\n * Errors\n */\n\n /// @notice error to denote that there is not enough margin for the transaction to go through\n /// @param accountMarketValue shows the account market value after the transaction is executed\n /// @param totalRequiredMargin shows the total required margin after the transaction is executed\n error InvalidTransactionNotEnoughMargin(int256 accountMarketValue, int256 totalRequiredMargin);\n\n /// @notice error to denote that there is not enough profit during profit withdrawal\n /// @param totalProfit shows the value of positions at the time of execution after removing amount specified\n error InvalidTransactionNotEnoughProfit(int256 totalProfit);\n\n /// @notice error to denote that there is enough margin, hence the liquidation is invalid\n /// @param accountMarketValue shows the account market value before liquidation\n /// @param totalRequiredMargin shows the total required margin before liquidation\n error InvalidLiquidationAccountAboveWater(int256 accountMarketValue, int256 totalRequiredMargin);\n\n /// @notice error to denote that there are active ranges present during token liquidation, hence the liquidation is invalid\n /// @param poolId shows the poolId for which range is active\n error InvalidLiquidationActiveRangePresent(uint32 poolId);\n\n /// @notice denotes withdrawal of profit in settlement token\n /// @param accountId serial number of the account\n /// @param amount amount of profit withdrawn\n event ProfitUpdated(uint256 indexed accountId, int256 amount);\n\n /**\n * Events\n */\n\n /// @notice denotes add or remove of margin\n /// @param accountId serial number of the account\n /// @param collateralId token in which margin is deposited\n /// @param amount amount of tokens deposited\n event MarginUpdated(uint256 indexed accountId, uint32 indexed collateralId, int256 amount, bool isSettleProfit);\n\n /// @notice denotes range position liquidation event\n /// @dev all range positions are liquidated and the current tokens inside the range are added in as token positions to the account\n /// @param accountId serial number of the account\n /// @param keeperAddress address of keeper who performed the liquidation\n /// @param liquidationFee total liquidation fee charged to the account\n /// @param keeperFee total liquidaiton fee paid to the keeper (positive only)\n /// @param insuranceFundFee total liquidaiton fee paid to the insurance fund (can be negative in case the account is not enought to cover the fee)\n event LiquidityPositionsLiquidated(\n uint256 indexed accountId,\n address indexed keeperAddress,\n int256 liquidationFee,\n int256 keeperFee,\n int256 insuranceFundFee,\n int256 accountMarketValueFinal\n );\n\n /// @notice denotes token position liquidation event\n /// @dev the selected token position is take from the current account and moved to liquidatorAccount at a discounted prive to current pool price\n /// @param accountId serial number of the account\n /// @param poolId id of the rage trade pool for whose position was liquidated\n /// @param keeperFee total liquidaiton fee paid to keeper\n /// @param insuranceFundFee total liquidaiton fee paid to the insurance fund (can be negative in case the account is not enough to cover the fee)\n event TokenPositionLiquidated(\n uint256 indexed accountId,\n uint32 indexed poolId,\n int256 keeperFee,\n int256 insuranceFundFee,\n int256 accountMarketValueFinal\n );\n\n /**\n * External methods\n */\n\n /// @notice changes deposit balance of 'vToken' by 'amount'\n /// @param account account to deposit balance into\n /// @param collateralId collateral id of the token\n /// @param amount amount of token to deposit or withdraw\n /// @param protocol set of all constants and token addresses\n /// @param checkMargin true to check if margin is available else false\n function updateMargin(\n Account.Info storage account,\n uint32 collateralId,\n int256 amount,\n Protocol.Info storage protocol,\n bool checkMargin\n ) external {\n _updateMargin(account, collateralId, amount, protocol, checkMargin, false);\n }\n\n /// @notice updates 'amount' of profit generated in settlement token\n /// @param account account to remove profit from\n /// @param amount amount of profit(settlement token) to add/remove\n /// @param protocol set of all constants and token addresses\n /// @param checkMargin true to check if margin is available else false\n function updateProfit(\n Account.Info storage account,\n int256 amount,\n Protocol.Info storage protocol,\n bool checkMargin\n ) external {\n _updateProfit(account, amount, protocol, checkMargin);\n }\n\n function settleProfit(Account.Info storage account, Protocol.Info storage protocol) external {\n _settleProfit(account, protocol);\n }\n\n /// @notice swaps 'vToken' of token amount equal to 'swapParams.amount'\n /// @notice if vTokenAmount>0 then the swap is a long or close short and if vTokenAmount<0 then swap is a short or close long\n /// @notice isNotional specifies whether the amount represents token amount (false) or vQuote amount(true)\n /// @notice isPartialAllowed specifies whether to revert (false) or to execute a partial swap (true)\n /// @notice sqrtPriceLimit threshold sqrt price which if crossed then revert or execute partial swap\n /// @param account account to swap tokens for\n /// @param poolId id of the pool to swap tokens for\n /// @param swapParams parameters for the swap (Includes - amount, sqrtPriceLimit, isNotional, isPartialAllowed)\n /// @param protocol set of all constants and token addresses\n /// @param checkMargin true to check if margin is available else false\n /// @return vTokenAmountOut amount of vToken after swap (user receiving then +ve, user paying then -ve)\n /// @return vQuoteAmountOut amount of vQuote after swap (user receiving then +ve, user paying then -ve)\n function swapToken(\n Account.Info storage account,\n uint32 poolId,\n IClearingHouseStructures.SwapParams memory swapParams,\n Protocol.Info storage protocol,\n bool checkMargin\n ) external returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n // make a swap. vQuoteIn and vTokenAmountOut (in and out wrt uniswap).\n // mints erc20 tokens in callback and send to the pool\n (vTokenAmountOut, vQuoteAmountOut) = account.tokenPositions.swapToken(account.id, poolId, swapParams, protocol);\n\n if (swapParams.settleProfit) {\n account._settleProfit(protocol);\n }\n // after all the stuff, account should be above water\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\n }\n\n /// @notice changes range liquidity 'vToken' of market value equal to 'vTokenNotional'\n /// @notice if 'liquidityDelta'>0 then liquidity is added and if 'liquidityChange'<0 then liquidity is removed\n /// @notice the liquidity change is reverted if the sqrt price at the time of execution is beyond 'slippageToleranceBps' of 'sqrtPriceCurrent' supplied\n /// @notice whenever liquidity change is done the external token position is taken out. If 'closeTokenPosition' is true this is swapped out else it is added to the current token position\n /// @param account account to change liquidity\n /// @param poolId id of the rage trade pool\n /// @param liquidityChangeParams parameters including lower tick, upper tick, liquidity delta, sqrtPriceCurrent, slippageToleranceBps, closeTokenPosition, limit order type\n /// @param protocol set of all constants and token addresses\n function liquidityChange(\n Account.Info storage account,\n uint32 poolId,\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\n Protocol.Info storage protocol,\n bool checkMargin\n )\n external\n returns (\n int256 vTokenAmountOut,\n int256 vQuoteAmountOut,\n uint256 notionalValueAbs\n )\n {\n // mint/burn tokens + fee + funding payment\n (vTokenAmountOut, vQuoteAmountOut) = account.tokenPositions.liquidityChange(\n account.id,\n poolId,\n liquidityChangeParams,\n protocol\n );\n\n if (liquidityChangeParams.settleProfit) {\n account._settleProfit(protocol);\n }\n // after all the stuff, account should be above water\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\n\n notionalValueAbs = protocol.getNotionalValue(poolId, vTokenAmountOut, vQuoteAmountOut);\n }\n\n /// @notice liquidates all range positions in case the account is under water\n /// charges a liquidation fee to the account and pays partially to the insurance fund and rest to the keeper.\n /// @dev insurance fund covers the remaining fee if the account market value is not enough\n /// @param account account to liquidate\n /// @param protocol set of all constants and token addresses\n /// @return keeperFee amount of liquidation fee paid to keeper\n /// @return insuranceFundFee amount of liquidation fee paid to insurance fund\n /// @return accountMarketValue account market value before liquidation\n function liquidateLiquidityPositions(Account.Info storage account, Protocol.Info storage protocol)\n external\n returns (\n int256 keeperFee,\n int256 insuranceFundFee,\n int256 accountMarketValue\n )\n {\n // check basis maintanace margin\n int256 totalRequiredMargin;\n uint256 notionalAmountClosed;\n\n (accountMarketValue, totalRequiredMargin) = account._getAccountValueAndRequiredMargin(false, protocol);\n\n // check and revert if account is above water\n if (accountMarketValue > totalRequiredMargin) {\n revert InvalidLiquidationAccountAboveWater(accountMarketValue, totalRequiredMargin);\n }\n // liquidate all liquidity positions\n notionalAmountClosed = account.tokenPositions.liquidateLiquidityPositions(account.id, protocol);\n\n // compute liquidation fees\n (keeperFee, insuranceFundFee) = _computeLiquidationFees(\n accountMarketValue,\n notionalAmountClosed,\n true,\n protocol.liquidationParams\n );\n\n account._updateVQuoteBalance(-(keeperFee + insuranceFundFee));\n }\n\n /// @notice liquidates token position specified by 'poolId' in case account is underwater\n /// charges a liquidation fee to the account and pays partially to the insurance fund and rest to the keeper.\n /// @dev closes position uptil a specified slippage threshold in protocol.liquidationParams\n /// @dev insurance fund covers the remaining fee if the account market value is not enough\n /// @dev if there is range position this reverts (liquidators are supposed to liquidate range positions first)\n /// @param account account to liquidate\n /// @param poolId id of the pool to liquidate\n /// @param protocol set of all constants and token addresses\n /// @return keeperFee amount of liquidation fee paid to keeper\n /// @return insuranceFundFee amount of liquidation fee paid to insurance fund\n function liquidateTokenPosition(\n Account.Info storage account,\n uint32 poolId,\n Protocol.Info storage protocol\n ) external returns (int256 keeperFee, int256 insuranceFundFee) {\n bool isPartialLiquidation;\n\n // check if there is range position and revert\n if (account.tokenPositions.isTokenRangeActive(poolId)) revert InvalidLiquidationActiveRangePresent(poolId);\n\n {\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\n false,\n protocol\n );\n\n // check and revert if account is above water\n if (accountMarketValue > totalRequiredMargin) {\n revert InvalidLiquidationAccountAboveWater(accountMarketValue, totalRequiredMargin);\n } else if (\n // check if account is underwater but within partial liquidation threshold\n accountMarketValue >\n totalRequiredMargin.mulDiv(protocol.liquidationParams.closeFactorMMThresholdBps, 1e4)\n ) {\n isPartialLiquidation = true;\n }\n }\n\n int256 tokensToTrade;\n {\n // get the net token position and tokensToTrade = -tokenPosition\n // since no ranges are supposed to be there so only tokenPosition is in vTokenPositionSet\n VTokenPosition.Info storage vTokenPosition = account.tokenPositions.getTokenPosition(poolId, false);\n tokensToTrade = -vTokenPosition.balance;\n uint256 tokenNotionalValue = tokensToTrade.absUint().mulDiv(\n protocol.getCachedVirtualTwapPriceX128(poolId),\n FixedPoint128.Q128\n );\n\n // check if the token position is less than a certain notional value\n // if so then liquidate the whole position even if partial liquidation is allowed\n // otherwise do partial liquidation\n if (isPartialLiquidation && tokenNotionalValue > protocol.liquidationParams.minNotionalLiquidatable) {\n tokensToTrade = tokensToTrade.mulDiv(protocol.liquidationParams.partialLiquidationCloseFactorBps, 1e4);\n }\n }\n\n int256 accountMarketValueFinal;\n {\n uint160 sqrtPriceLimit;\n {\n // calculate sqrt price limit based on slippage threshold\n uint160 sqrtTwapPrice = protocol.getVirtualTwapSqrtPriceX96(poolId);\n if (tokensToTrade > 0) {\n sqrtPriceLimit = uint256(sqrtTwapPrice)\n .mulDiv(1e4 + protocol.liquidationParams.liquidationSlippageSqrtToleranceBps, 1e4)\n .toUint160();\n } else {\n sqrtPriceLimit = uint256(sqrtTwapPrice)\n .mulDiv(1e4 - protocol.liquidationParams.liquidationSlippageSqrtToleranceBps, 1e4)\n .toUint160();\n }\n }\n\n // close position uptil sqrt price limit\n (, int256 vQuoteAmountSwapped) = account.tokenPositions.swapToken(\n account.id,\n poolId,\n IClearingHouseStructures.SwapParams({\n amount: tokensToTrade,\n sqrtPriceLimit: sqrtPriceLimit,\n isNotional: false,\n isPartialAllowed: true,\n settleProfit: false\n }),\n protocol\n );\n\n // get the account market value after closing the position\n accountMarketValueFinal = account._getAccountValue(protocol);\n\n // compute liquidation fees\n (keeperFee, insuranceFundFee) = _computeLiquidationFees(\n accountMarketValueFinal,\n vQuoteAmountSwapped.absUint(),\n false,\n protocol.liquidationParams\n );\n }\n\n // deduct liquidation fees from account\n account._updateVQuoteBalance(-(keeperFee + insuranceFundFee));\n\n emit TokenPositionLiquidated(account.id, poolId, keeperFee, insuranceFundFee, accountMarketValueFinal);\n }\n\n /// @notice removes limit order based on the current price position (keeper call)\n /// @param account account to liquidate\n /// @param poolId id of the pool for the range\n /// @param tickLower lower tick index for the range\n /// @param tickUpper upper tick index for the range\n /// @param protocol platform constants\n function removeLimitOrder(\n Account.Info storage account,\n uint32 poolId,\n int24 tickLower,\n int24 tickUpper,\n uint256 limitOrderFee,\n Protocol.Info storage protocol\n ) external {\n account.tokenPositions.removeLimitOrder(account.id, poolId, tickLower, tickUpper, protocol);\n\n account._updateVQuoteBalance(-int256(limitOrderFee));\n }\n\n /**\n * External view methods\n */\n\n /// @notice returns market value for the account positions based on current market conditions\n /// @param account account to check\n /// @param protocol set of all constants and token addresses\n /// @return accountPositionProfits total market value of all the positions (token ) and deposits\n function getAccountPositionProfits(Account.Info storage account, Protocol.Info storage protocol)\n external\n view\n returns (int256 accountPositionProfits)\n {\n return account._getAccountPositionProfits(protocol);\n }\n\n /// @notice returns market value and required margin for the account based on current market conditions\n /// @dev (In case requiredMargin < minRequiredMargin then requiredMargin = minRequiredMargin)\n /// @param account account to check\n /// @param isInitialMargin true to use initial margin factor and false to use maintainance margin factor for calcualtion of required margin\n /// @param protocol set of all constants and token addresses\n /// @return accountMarketValue total market value of all the positions (token ) and deposits\n /// @return totalRequiredMargin total margin required to keep the account above selected margin requirement (intial/maintainance)\n function getAccountValueAndRequiredMargin(\n Account.Info storage account,\n bool isInitialMargin,\n Protocol.Info storage protocol\n ) external view returns (int256 accountMarketValue, int256 totalRequiredMargin) {\n return account._getAccountValueAndRequiredMargin(isInitialMargin, protocol);\n }\n\n /// @notice checks if market value > required margin else revert with InvalidTransactionNotEnoughMargin\n /// @param account account to check\n /// @param isInitialMargin true to use initialMarginFactor and false to use maintainance margin factor for calcualtion of required margin\n /// @param protocol set of all constants and token addresses\n function checkIfMarginAvailable(\n Account.Info storage account,\n bool isInitialMargin,\n Protocol.Info storage protocol\n ) external view {\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\n isInitialMargin,\n protocol\n );\n if (accountMarketValue < totalRequiredMargin)\n revert InvalidTransactionNotEnoughMargin(accountMarketValue, totalRequiredMargin);\n }\n\n /// @notice checks if profit is available to withdraw settlement token (token value of all positions > 0) else revert with InvalidTransactionNotEnoughProfit\n /// @param account account to check\n /// @param protocol set of all constants and token addresses\n function checkIfProfitAvailable(Account.Info storage account, Protocol.Info storage protocol) external view {\n _checkIfProfitAvailable(account, protocol);\n }\n\n /// @notice gets information about all the collateral and positions in the account\n /// @param account ref to the account state\n /// @param protocol ref to the protocol state\n /// @return owner of the account\n /// @return vQuoteBalance amount of vQuote in the account\n /// @return collateralDeposits list of all the collateral amounts\n /// @return tokenPositions list of all the token and liquidity positions\n function getInfo(Account.Info storage account, Protocol.Info storage protocol)\n external\n view\n returns (\n address owner,\n int256 vQuoteBalance,\n IClearingHouseStructures.CollateralDepositView[] memory collateralDeposits,\n IClearingHouseStructures.VTokenPositionView[] memory tokenPositions\n )\n {\n owner = account.owner;\n collateralDeposits = account.collateralDeposits.getInfo(protocol);\n (vQuoteBalance, tokenPositions) = account.tokenPositions.getInfo();\n }\n\n /// @notice gets the net position of the account for a given pool\n /// @param account ref to the account state\n /// @param poolId id of the pool\n /// @param protocol ref to the protocol state\n /// @return netPosition net position of the account for the pool\n function getNetPosition(\n Account.Info storage account,\n uint32 poolId,\n Protocol.Info storage protocol\n ) external view returns (int256 netPosition) {\n return account.tokenPositions.getNetPosition(poolId, protocol);\n }\n\n /**\n * Internal methods\n */\n\n function updateAccountPoolPrices(Account.Info storage account, Protocol.Info storage protocol) internal {\n account.tokenPositions.updateOpenPoolPrices(protocol);\n }\n\n /// @notice settles profit or loss for the account\n /// @param account ref to the account state\n /// @param protocol ref to the protocol state\n function _settleProfit(Account.Info storage account, Protocol.Info storage protocol) internal {\n int256 profits = account._getAccountPositionProfits(protocol);\n uint32 settlementCollateralId = AddressHelper.truncate(protocol.settlementToken);\n if (profits > 0) {\n account._updateProfit(-profits, protocol, false);\n account._updateMargin({\n collateralId: settlementCollateralId,\n amount: profits,\n protocol: protocol,\n checkMargin: false,\n isSettleProfit: true\n });\n } else if (profits < 0) {\n uint256 balance = account.collateralDeposits.getBalance(settlementCollateralId);\n uint256 profitAbsUint = uint256(-profits);\n uint256 balanceToUpdate = balance > profitAbsUint ? profitAbsUint : balance;\n if (balanceToUpdate > 0) {\n account._updateMargin({\n collateralId: settlementCollateralId,\n amount: -balanceToUpdate.toInt256(),\n protocol: protocol,\n checkMargin: false,\n isSettleProfit: true\n });\n account._updateProfit(balanceToUpdate.toInt256(), protocol, false);\n }\n }\n }\n\n /// @notice updates 'amount' of profit generated in settlement token\n /// @param account account to remove profit from\n /// @param amount amount of profit(settlement token) to add/remove\n /// @param protocol set of all constants and token addresses\n /// @param checkMargin true to check if margin is available else false\n function _updateProfit(\n Account.Info storage account,\n int256 amount,\n Protocol.Info storage protocol,\n bool checkMargin\n ) internal {\n account._updateVQuoteBalance(amount);\n\n if (checkMargin && amount < 0) {\n account._checkIfProfitAvailable(protocol);\n account._checkIfMarginAvailable(true, protocol);\n }\n\n emit ProfitUpdated(account.id, amount);\n }\n\n /// @notice changes deposit balance of 'vToken' by 'amount'\n /// @param account account to deposit balance into\n /// @param collateralId collateral id of the token\n /// @param amount amount of token to deposit or withdraw\n /// @param protocol set of all constants and token addresses\n /// @param checkMargin true to check if margin is available else false\n function _updateMargin(\n Account.Info storage account,\n uint32 collateralId,\n int256 amount,\n Protocol.Info storage protocol,\n bool checkMargin,\n bool isSettleProfit\n ) internal {\n if (amount > 0) {\n account.collateralDeposits.increaseBalance(collateralId, uint256(amount));\n } else {\n account.collateralDeposits.decreaseBalance(collateralId, uint256(-amount));\n if (checkMargin) account._checkIfMarginAvailable(true, protocol);\n }\n\n emit MarginUpdated(account.id, collateralId, amount, isSettleProfit);\n }\n\n /// @notice updates the vQuote balance for 'account' by 'amount'\n /// @param account pointer to 'account' struct\n /// @param amount amount of balance to update\n /// @return balanceAdjustments vToken and vQuote balance changes of the account\n function _updateVQuoteBalance(Account.Info storage account, int256 amount)\n internal\n returns (IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments)\n {\n balanceAdjustments = IClearingHouseStructures.BalanceAdjustments(amount, 0, 0);\n account.tokenPositions.vQuoteBalance += balanceAdjustments.vQuoteIncrease;\n }\n\n /**\n * Internal view methods\n */\n\n /// @notice ensures that the account has enough margin to cover the required margin\n /// @param account ref to the account state\n /// @param protocol ref to the protocol state\n function _checkIfMarginAvailable(\n Account.Info storage account,\n bool isInitialMargin,\n Protocol.Info storage protocol\n ) internal view {\n (int256 accountMarketValue, int256 totalRequiredMargin) = account._getAccountValueAndRequiredMargin(\n isInitialMargin,\n protocol\n );\n if (accountMarketValue < totalRequiredMargin)\n revert InvalidTransactionNotEnoughMargin(accountMarketValue, totalRequiredMargin);\n }\n\n /// @notice ensures that the account has non negative profit\n /// @param account ref to the account state\n /// @param protocol ref to the protocol state\n function _checkIfProfitAvailable(Account.Info storage account, Protocol.Info storage protocol) internal view {\n int256 totalPositionValue = account._getAccountPositionProfits(protocol);\n if (totalPositionValue < 0) revert InvalidTransactionNotEnoughProfit(totalPositionValue);\n }\n\n /// @notice gets the amount of account's position profits\n /// @param account ref to the account state\n /// @param protocol ref to the protocol state\n function _getAccountPositionProfits(Account.Info storage account, Protocol.Info storage protocol)\n internal\n view\n returns (int256 accountPositionProfits)\n {\n accountPositionProfits = account.tokenPositions.getAccountMarketValue(protocol);\n }\n\n /// @notice gets market value for the account based on current market conditions\n /// @param account ref to the account state\n /// @param protocol set of all constants and token addresses\n /// @return accountMarketValue total market value of all the positions (token ) and deposits\n function _getAccountValue(Account.Info storage account, Protocol.Info storage protocol)\n internal\n view\n returns (int256 accountMarketValue)\n {\n accountMarketValue = account._getAccountPositionProfits(protocol);\n accountMarketValue += account.collateralDeposits.marketValue(protocol);\n return (accountMarketValue);\n }\n\n /// @notice gets market value and req margin for the account based on current market conditions\n /// @param account ref to the account state\n /// @param isInitialMargin true to use initialMarginFactor and false to use maintainance margin factor for calcualtion of required margin\n /// @param protocol set of all constants and token addresses\n /// @return accountMarketValue total market value of all the positions (token) and deposits\n /// @return totalRequiredMargin total required margin for the account\n function _getAccountValueAndRequiredMargin(\n Account.Info storage account,\n bool isInitialMargin,\n Protocol.Info storage protocol\n ) internal view returns (int256 accountMarketValue, int256 totalRequiredMargin) {\n accountMarketValue = account._getAccountValue(protocol);\n\n totalRequiredMargin = account.tokenPositions.getRequiredMargin(isInitialMargin, protocol);\n if (!account.tokenPositions.isEmpty()) {\n totalRequiredMargin = totalRequiredMargin < int256(protocol.minRequiredMargin)\n ? int256(protocol.minRequiredMargin)\n : totalRequiredMargin;\n }\n return (accountMarketValue, totalRequiredMargin);\n }\n\n /// @notice checks if 'account' is initialized\n /// @param account pointer to 'account' struct\n function _isInitialized(Account.Info storage account) internal view returns (bool) {\n return !account.owner.isZero();\n }\n\n /**\n * Internal pure methods\n */\n\n /// @notice computes keeper fee and insurance fund fee in case of liquidity position liquidation\n /// @dev keeperFee = liquidationFee*(1-insuranceFundFeeShare)\n /// @dev insuranceFundFee = accountMarketValue - keeperFee (if accountMarketValue is not enough to cover the fees) else insurancFundFee = liquidationFee - keeperFee\n /// @param accountMarketValue market value of account\n /// @param notionalAmountClosed notional value of position closed\n /// @param isRangeLiquidation - true for range liquidation and false for token liquidation\n /// @param liquidationParams parameters including insuranceFundFeeShareBps\n /// @return keeperFee map of vTokens allowed on the platform\n /// @return insuranceFundFee poolwrapper for token\n function _computeLiquidationFees(\n int256 accountMarketValue,\n uint256 notionalAmountClosed,\n bool isRangeLiquidation,\n IClearingHouseStructures.LiquidationParams memory liquidationParams\n ) internal pure returns (int256 keeperFee, int256 insuranceFundFee) {\n uint256 liquidationFee;\n\n if (isRangeLiquidation) {\n liquidationFee = notionalAmountClosed.mulDiv(liquidationParams.rangeLiquidationFeeFraction, 1e5);\n if (liquidationParams.maxRangeLiquidationFees < liquidationFee)\n liquidationFee = liquidationParams.maxRangeLiquidationFees;\n } else {\n liquidationFee = notionalAmountClosed.mulDiv(liquidationParams.tokenLiquidationFeeFraction, 1e5);\n }\n\n int256 liquidationFeeInt = liquidationFee.toInt256();\n\n keeperFee = liquidationFeeInt.mulDiv(1e4 - liquidationParams.insuranceFundFeeShareBps, 1e4);\n if (accountMarketValue - liquidationFeeInt < 0) {\n insuranceFundFee = accountMarketValue - keeperFee;\n } else {\n insuranceFundFee = liquidationFeeInt - keeperFee;\n }\n }\n}\n" + }, + "contracts/test/mocks/VPoolWrapperMock.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { IVPoolWrapper } from '../../interfaces/IVPoolWrapper.sol';\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\n\ncontract VPoolWrapperMock is IVPoolWrapper {\n mapping(int24 => mapping(int24 => IVPoolWrapper.WrapperValuesInside)) _getValuesInside;\n uint24 public uniswapFeePips; // fee collected by Uniswap\n uint24 public liquidityFeePips; // fee paid to liquidity providers, in 1e6\n uint24 public protocolFeePips; // fee paid to DAO treasury\n\n struct LiquidityRate {\n uint256 vQuotePerLiquidity;\n uint256 vTokenPerLiquidity;\n }\n mapping(int24 => mapping(int24 => LiquidityRate)) internal _liquidityRates;\n\n IUniswapV3Pool public vPool;\n\n function initialize(InitializeVPoolWrapperParams calldata params) external {}\n\n function updateGlobalFundingState(bool useZeroFundingRate) public {}\n\n function getValuesInside(int24 tickLower, int24 tickUpper)\n public\n view\n returns (WrapperValuesInside memory wrapperValuesInside)\n {\n return _getValuesInside[tickLower][tickUpper];\n }\n\n function getExtrapolatedValuesInside(int24 tickLower, int24 tickUpper)\n public\n view\n returns (WrapperValuesInside memory wrapperValuesInside)\n {\n return _getValuesInside[tickLower][tickUpper];\n }\n\n function setValuesInside(\n int24 tickLower,\n int24 tickUpper,\n int256 sumAX128,\n int256 sumBInsideX128,\n int256 sumFpInsideX128,\n uint256 sumFeeInsideX128\n ) external {\n _getValuesInside[tickLower][tickUpper] = IVPoolWrapper.WrapperValuesInside(\n sumAX128,\n sumBInsideX128,\n sumFpInsideX128,\n sumFeeInsideX128\n );\n }\n\n function setVPool(address vPoolAddress) external {\n vPool = IUniswapV3Pool(vPoolAddress);\n }\n\n uint256 _liquidity;\n\n function setLiquidityRates(\n int24 tickLower,\n int24 tickUpper,\n uint256 vQuotePerLiquidity,\n uint256 vTokenPerLiquidity\n ) external {\n LiquidityRate storage liquidityRate = _liquidityRates[tickLower][tickUpper];\n liquidityRate.vQuotePerLiquidity = vQuotePerLiquidity;\n liquidityRate.vTokenPerLiquidity = vTokenPerLiquidity;\n }\n\n function mint(\n int24 tickLower,\n int24 tickUpper,\n uint128 liquidity\n )\n external\n returns (\n uint256 vTokenAmount,\n uint256 vQuoteAmount,\n WrapperValuesInside memory wrapperValuesInside\n )\n {\n _liquidity += liquidity;\n\n vTokenAmount = _liquidityRates[tickLower][tickUpper].vTokenPerLiquidity * liquidity;\n vQuoteAmount = _liquidityRates[tickLower][tickUpper].vQuotePerLiquidity * liquidity;\n wrapperValuesInside = getValuesInside(tickLower, tickUpper);\n }\n\n function burn(\n int24 tickLower,\n int24 tickUpper,\n uint128 liquidity\n )\n external\n returns (\n uint256 vTokenAmount,\n uint256 vQuoteAmount,\n WrapperValuesInside memory wrapperValuesInside\n )\n {\n _liquidity -= liquidity;\n\n vQuoteAmount = _liquidityRates[tickLower][tickUpper].vQuotePerLiquidity * liquidity;\n vTokenAmount = _liquidityRates[tickLower][tickUpper].vTokenPerLiquidity * liquidity;\n wrapperValuesInside = getValuesInside(tickLower, tickUpper);\n }\n\n function getSumAX128() external pure returns (int256) {\n return 20 * (1 << 128);\n }\n\n function getExtrapolatedSumAX128() external pure returns (int256) {\n return 20 * (1 << 128);\n }\n\n function swapTokenAmount(int256 vTokenAmount) external pure returns (int256) {\n return vTokenAmount * (-4000);\n }\n\n function swap(\n bool swapVTokenForVQuote, // zeroForOne\n int256 amountSpecified,\n uint160\n ) public pure returns (SwapResult memory swapResult) {\n if (amountSpecified > 0 == swapVTokenForVQuote) {\n // ETH exactIn || ETH exactOut\n swapResult.vTokenIn = amountSpecified;\n swapResult.vQuoteIn = -amountSpecified * 4000;\n } else {\n // USDC exactIn || USDC exactOut\n swapResult.vTokenIn = -amountSpecified / 4000;\n swapResult.vQuoteIn = amountSpecified;\n }\n }\n\n function swapTokenNotional(int256 vTokenNotional) external pure returns (int256) {\n return vTokenNotional / (4000);\n }\n\n function collectAccruedProtocolFee() external pure returns (uint256 accruedProtocolFeeLast) {\n accruedProtocolFeeLast = 0;\n }\n}\n" + }, + "contracts/test/mocks/AccountProtocolInfoMock.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Protocol } from '../../libraries/Protocol.sol';\nimport { AddressHelper } from '../../libraries/AddressHelper.sol';\n\nimport { IClearingHouseStructures } from '../../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\nimport { IVToken } from '../../interfaces/IVToken.sol';\n\nabstract contract AccountProtocolInfoMock {\n using AddressHelper for address;\n\n Protocol.Info public protocol;\n\n uint256 public fixFee;\n\n function setAccountStorage(\n IClearingHouseStructures.LiquidationParams calldata _liquidationParams,\n uint256 _minRequiredMargin,\n uint256 _removeLimitOrderFee,\n uint256 _minimumOrderNotional,\n uint256 _fixFee\n ) external {\n protocol.liquidationParams = _liquidationParams;\n protocol.minRequiredMargin = _minRequiredMargin;\n protocol.removeLimitOrderFee = _removeLimitOrderFee;\n protocol.minimumOrderNotional = _minimumOrderNotional;\n fixFee = _fixFee;\n }\n\n function registerPool(IClearingHouseStructures.Pool calldata poolInfo) external virtual {\n uint32 poolId = address(poolInfo.vToken).truncate();\n\n // this check is not present here as the tests change some things.\n // this method is only used in these tests:\n // AccountBasic, AccountRealistic, MarketValueAndReqMargin, VTokenPositionSet\n // assert(address(protocol.pools[poolId].vToken).eq(address(0)));\n\n protocol.pools[poolId] = poolInfo;\n }\n\n function setVQuoteAddress(IVQuote _vQuote) external {\n protocol.vQuote = _vQuote;\n }\n}\n" + }, + "contracts/libraries/Protocol.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { Math } from '@openzeppelin/contracts/utils/math/Math.sol';\n\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IVQuote } from '../interfaces/IVQuote.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\n\nimport { PriceMath } from './PriceMath.sol';\nimport { SafeCast } from './SafeCast.sol';\nimport { SignedMath } from './SignedMath.sol';\nimport { SignedFullMath } from './SignedFullMath.sol';\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\nimport { Block } from './Block.sol';\nimport { SafeCast } from './SafeCast.sol';\n\n/// @title Protocol storage functions\n/// @dev This is used as main storage interface containing protocol info\nlibrary Protocol {\n using FullMath for uint256;\n using PriceMath for uint160;\n using PriceMath for uint256;\n using SignedMath for int256;\n using SignedFullMath for int256;\n using SafeCast for uint256;\n using UniswapV3PoolHelper for IUniswapV3Pool;\n using SafeCast for uint256;\n\n using Protocol for Protocol.Info;\n\n struct PriceCache {\n uint32 updateBlockNumber;\n uint224 virtualPriceX128;\n uint224 realPriceX128;\n bool isDeviationBreached;\n }\n struct Info {\n // poolId => PoolInfo\n mapping(uint32 => IClearingHouseStructures.Pool) pools;\n // collateralId => CollateralInfo\n mapping(uint32 => IClearingHouseStructures.Collateral) collaterals;\n // iterable and increasing list of pools (used for admin functions)\n uint32[] poolIds;\n // settlement token (default collateral)\n IERC20 settlementToken;\n // virtual quote token (sort of fake USDC), is always token1 in uniswap pools\n IVQuote vQuote;\n // accounting settings\n IClearingHouseStructures.LiquidationParams liquidationParams;\n uint256 minRequiredMargin;\n uint256 removeLimitOrderFee;\n uint256 minimumOrderNotional;\n // price cache\n mapping(uint32 => PriceCache) priceCache;\n // reserved for adding slots in future\n uint256[100] _emptySlots;\n }\n\n function updatePoolPriceCache(Protocol.Info storage protocol, uint32 poolId) internal {\n uint32 blockNumber = Block.number();\n\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\n if (poolPriceCache.updateBlockNumber == blockNumber) {\n return;\n }\n\n uint256 realPriceX128 = protocol.getRealTwapPriceX128(poolId);\n uint256 virtualPriceX128 = protocol.getVirtualTwapPriceX128(poolId);\n\n // In case the price is breaching the Q224 limit, we do not cache it\n uint256 Q224 = 1 << 224;\n if (realPriceX128 >= Q224 || virtualPriceX128 >= Q224) {\n return;\n }\n\n uint16 maxDeviationBps = protocol.pools[poolId].settings.maxVirtualPriceDeviationRatioBps;\n if (\n // if virtual price is too off from real price then screw that, we'll just use real price\n (int256(realPriceX128) - int256(virtualPriceX128)).absUint() > realPriceX128.mulDiv(maxDeviationBps, 1e4)\n ) {\n poolPriceCache.isDeviationBreached = true;\n } else {\n poolPriceCache.isDeviationBreached = false;\n }\n poolPriceCache.realPriceX128 = realPriceX128.toUint224();\n poolPriceCache.virtualPriceX128 = virtualPriceX128.toUint224();\n poolPriceCache.updateBlockNumber = blockNumber;\n }\n\n /// @notice gets the uniswap v3 pool address for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return UniswapV3Pool contract object\n function vPool(Protocol.Info storage protocol, uint32 poolId) internal view returns (IUniswapV3Pool) {\n return protocol.pools[poolId].vPool;\n }\n\n /// @notice gets the wrapper address for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return VPoolWrapper contract object\n function vPoolWrapper(Protocol.Info storage protocol, uint32 poolId) internal view returns (IVPoolWrapper) {\n return protocol.pools[poolId].vPoolWrapper;\n }\n\n /// @notice gets the virtual twap sqrt price for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return sqrtPriceX96 virtual twap sqrt price\n function getVirtualTwapSqrtPriceX96(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint160 sqrtPriceX96)\n {\n IClearingHouseStructures.Pool storage pool = protocol.pools[poolId];\n return pool.vPool.twapSqrtPrice(pool.settings.twapDuration);\n }\n\n /// @notice gets the virtual current sqrt price for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return sqrtPriceX96 virtual current sqrt price\n function getVirtualCurrentSqrtPriceX96(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint160 sqrtPriceX96)\n {\n return protocol.pools[poolId].vPool.sqrtPriceCurrent();\n }\n\n /// @notice gets the virtual current tick for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return tick virtual current tick\n function getVirtualCurrentTick(Protocol.Info storage protocol, uint32 poolId) internal view returns (int24 tick) {\n return protocol.pools[poolId].vPool.tickCurrent();\n }\n\n /// @notice gets the virtual twap price for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return priceX128 virtual twap price\n function getVirtualTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint256 priceX128)\n {\n return protocol.getVirtualTwapSqrtPriceX96(poolId).toPriceX128();\n }\n\n /// @notice gets the virtual current price for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return priceX128 virtual current price\n function getVirtualCurrentPriceX128(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint256 priceX128)\n {\n return protocol.getVirtualCurrentSqrtPriceX96(poolId).toPriceX128();\n }\n\n /// @notice gets the real twap price for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return priceX128 virtual twap price\n function getRealTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint256 priceX128)\n {\n IClearingHouseStructures.Pool storage pool = protocol.pools[poolId];\n return pool.settings.oracle.getTwapPriceX128(pool.settings.twapDuration);\n }\n\n /// @notice gets the twap prices with deviation check for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return realPriceX128 the real price\n /// @return virtualPriceX128 the virtual price if under deviation else real price\n function getTwapPricesWithDeviationCheck(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint256 realPriceX128, uint256 virtualPriceX128)\n {\n realPriceX128 = protocol.getRealTwapPriceX128(poolId);\n virtualPriceX128 = protocol.getVirtualTwapPriceX128(poolId);\n\n uint16 maxDeviationBps = protocol.pools[poolId].settings.maxVirtualPriceDeviationRatioBps;\n uint256 priceDeltaX128 = realPriceX128 > virtualPriceX128\n ? realPriceX128 - virtualPriceX128\n : virtualPriceX128 - realPriceX128;\n if (priceDeltaX128 > realPriceX128.mulDiv(maxDeviationBps, 1e4)) {\n // if virtual price is too off from real price then screw that, we'll just use real price\n virtualPriceX128 = realPriceX128;\n }\n return (realPriceX128, virtualPriceX128);\n }\n\n function getCachedVirtualTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint256 priceX128)\n {\n uint32 blockNumber = Block.number();\n\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\n if (poolPriceCache.updateBlockNumber == blockNumber) {\n return poolPriceCache.virtualPriceX128;\n } else {\n return protocol.getVirtualTwapPriceX128(poolId);\n }\n }\n\n function getCachedTwapPricesWithDeviationCheck(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint256 realPriceX128, uint256 virtualPriceX128)\n {\n uint32 blockNumber = Block.number();\n\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\n if (poolPriceCache.updateBlockNumber == blockNumber) {\n if (poolPriceCache.isDeviationBreached) {\n return (poolPriceCache.realPriceX128, poolPriceCache.realPriceX128);\n } else {\n return (poolPriceCache.realPriceX128, poolPriceCache.virtualPriceX128);\n }\n } else {\n return protocol.getTwapPricesWithDeviationCheck(poolId);\n }\n }\n\n function getCachedRealTwapPriceX128(Protocol.Info storage protocol, uint32 poolId)\n internal\n view\n returns (uint256 priceX128)\n {\n uint32 blockNumber = Block.number();\n\n PriceCache storage poolPriceCache = protocol.priceCache[poolId];\n if (poolPriceCache.updateBlockNumber == blockNumber) {\n return poolPriceCache.realPriceX128;\n } else {\n return protocol.getRealTwapPriceX128(poolId);\n }\n }\n\n /// @notice gets the margin ratio for a poolId\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @param isInitialMargin whether to use initial margin or maintainance margin\n /// @return margin rato in bps\n function getMarginRatioBps(\n Protocol.Info storage protocol,\n uint32 poolId,\n bool isInitialMargin\n ) internal view returns (uint16) {\n if (isInitialMargin) {\n return protocol.pools[poolId].settings.initialMarginRatioBps;\n } else {\n return protocol.pools[poolId].settings.maintainanceMarginRatioBps;\n }\n }\n\n /// @notice checks if the pool is cross margined\n /// @param protocol ref to the protocol state\n /// @param poolId the poolId of the pool\n /// @return bool whether the pool is cross margined\n function isPoolCrossMargined(Protocol.Info storage protocol, uint32 poolId) internal view returns (bool) {\n return protocol.pools[poolId].settings.isCrossMargined;\n }\n\n /// @notice Gives notional value of the given vToken and vQuote amounts\n /// @param protocol platform constants\n /// @param poolId id of the rage trade pool\n /// @param vTokenAmount amount of tokens\n /// @param vQuoteAmount amount of base\n /// @return notionalValue for the given token and vQuote amounts\n function getNotionalValue(\n Protocol.Info storage protocol,\n uint32 poolId,\n int256 vTokenAmount,\n int256 vQuoteAmount\n ) internal view returns (uint256 notionalValue) {\n return\n vTokenAmount.absUint().mulDiv(protocol.getCachedVirtualTwapPriceX128(poolId), FixedPoint128.Q128) +\n vQuoteAmount.absUint();\n }\n\n /// @notice Gives notional value of the given token amount\n /// @param protocol platform constants\n /// @param poolId id of the rage trade pool\n /// @param vTokenAmount amount of tokens\n /// @return notionalValue for the given token and vQuote amounts\n function getNotionalValue(\n Protocol.Info storage protocol,\n uint32 poolId,\n int256 vTokenAmount\n ) internal view returns (uint256 notionalValue) {\n return protocol.getNotionalValue(poolId, vTokenAmount, 0);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a / b + (a % b == 0 ? 0 : 1);\n }\n}\n" + }, + "contracts/libraries/Block.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface ArbSys {\n /**\n * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)\n * @return block number as int\n */\n function arbBlockNumber() external view returns (uint256);\n}\n\n/// @title Library for getting block number for the current chain\nlibrary Block {\n /// @notice Get block number\n /// @return block number as uint32\n function number() internal view returns (uint32) {\n uint256 chainId = block.chainid;\n if (chainId == 42161 || chainId == 421611 || chainId == 421612) {\n return uint32(ArbSys(address(100)).arbBlockNumber());\n } else {\n return uint32(block.number);\n }\n }\n}\n" + }, + "contracts/libraries/CollateralDeposit.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\n\nimport { Protocol } from './Protocol.sol';\nimport { AddressHelper } from './AddressHelper.sol';\nimport { SignedFullMath } from './SignedFullMath.sol';\nimport { Uint32L8ArrayLib } from './Uint32L8Array.sol';\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\n\n/// @title Collateral deposit set functions\nlibrary CollateralDeposit {\n using AddressHelper for address;\n using SafeCast for uint256;\n using SignedFullMath for int256;\n using Uint32L8ArrayLib for uint32[8];\n\n error InsufficientCollateralBalance();\n\n struct Set {\n // Fixed length array of collateralId = collateralAddress.truncate()\n // Supports upto 8 different collaterals in an account.\n // Collision is possible, i.e. collateralAddress1.truncate() == collateralAddress2.truncate()\n // However the possibility is 1/2**32, which is negligible.\n // There are checks that prevent use of a different collateralAddress for a given collateralId.\n // If there is a geniune collision, a wrapper for the ERC20 token can deployed such that\n // there are no collisions with wrapper and the wrapped ERC20 can be used as collateral.\n uint32[8] active; // array of collateralIds\n mapping(uint32 => uint256) deposits; // collateralId => deposit amount\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\n }\n\n function getBalance(CollateralDeposit.Set storage set, uint32 collateralId) internal view returns (uint256) {\n return set.deposits[collateralId];\n }\n\n /// @notice Increase the deposit amount of a given collateralId\n /// @param set CollateralDepositSet of the account\n /// @param collateralId The collateralId of the collateral to increase the deposit amount of\n /// @param amount The amount to increase the deposit amount of the collateral by\n function increaseBalance(\n CollateralDeposit.Set storage set,\n uint32 collateralId,\n uint256 amount\n ) internal {\n set.active.include(collateralId);\n\n set.deposits[collateralId] += amount;\n }\n\n /// @notice Decrease the deposit amount of a given collateralId\n /// @param set CollateralDepositSet of the account\n /// @param collateralId The collateralId of the collateral to decrease the deposit amount of\n /// @param amount The amount to decrease the deposit amount of the collateral by\n function decreaseBalance(\n CollateralDeposit.Set storage set,\n uint32 collateralId,\n uint256 amount\n ) internal {\n if (set.deposits[collateralId] < amount) revert InsufficientCollateralBalance();\n set.deposits[collateralId] -= amount;\n\n if (set.deposits[collateralId] == 0) {\n set.active.exclude(collateralId);\n }\n }\n\n /// @notice Get the market value of all the collateral deposits in settlementToken denomination\n /// @param set CollateralDepositSet of the account\n /// @param protocol Global protocol state\n /// @return The market value of all the collateral deposits in settlementToken denomination\n function marketValue(CollateralDeposit.Set storage set, Protocol.Info storage protocol)\n internal\n view\n returns (int256)\n {\n int256 accountMarketValue;\n for (uint8 i = 0; i < set.active.length; i++) {\n uint32 collateralId = set.active[i];\n\n if (collateralId == 0) break;\n IClearingHouseStructures.Collateral storage collateral = protocol.collaterals[collateralId];\n\n accountMarketValue += set.deposits[collateralId].toInt256().mulDiv(\n collateral.settings.oracle.getTwapPriceX128(collateral.settings.twapDuration),\n FixedPoint128.Q128\n );\n }\n return accountMarketValue;\n }\n\n /// @notice Get information about all the collateral deposits\n /// @param set CollateralDepositSet of the account\n /// @param protocol Global protocol state\n /// @return collateralDeposits Information about all the collateral deposits\n function getInfo(CollateralDeposit.Set storage set, Protocol.Info storage protocol)\n internal\n view\n returns (IClearingHouseStructures.CollateralDepositView[] memory collateralDeposits)\n {\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\n collateralDeposits = new IClearingHouseStructures.CollateralDepositView[](numberOfTokenPositions);\n\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\n collateralDeposits[i].collateral = protocol.collaterals[set.active[i]].token;\n collateralDeposits[i].balance = set.deposits[set.active[i]];\n }\n }\n}\n" + }, + "contracts/libraries/LiquidityPositionSet.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.4;\n\nimport { LiquidityPosition } from './LiquidityPosition.sol';\nimport { Protocol } from './Protocol.sol';\nimport { Uint48Lib } from './Uint48.sol';\nimport { Uint48L5ArrayLib } from './Uint48L5Array.sol';\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\n\n/// @title Liquidity position set functions\nlibrary LiquidityPositionSet {\n using LiquidityPosition for LiquidityPosition.Info;\n using LiquidityPositionSet for LiquidityPosition.Set;\n using Protocol for Protocol.Info;\n using Uint48Lib for int24;\n using Uint48Lib for uint48;\n using Uint48L5ArrayLib for uint48[5];\n\n error LPS_IllegalTicks(int24 tickLower, int24 tickUpper);\n error LPS_DeactivationFailed(int24 tickLower, int24 tickUpper, uint256 liquidity);\n error LPS_InactiveRange();\n\n /// @notice denotes token position change due to liquidity add/remove\n /// @param accountId serial number of the account\n /// @param poolId address of token whose position was taken\n /// @param tickLower lower tick of the range updated\n /// @param tickUpper upper tick of the range updated\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\n event TokenPositionChangedDueToLiquidityChanged(\n uint256 indexed accountId,\n uint32 indexed poolId,\n int24 tickLower,\n int24 tickUpper,\n int256 vTokenAmountOut\n );\n\n /**\n * Internal methods\n */\n\n /// @notice activates a position by initializing it and adding it to the set\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param tickLower lower tick of the range to be activated\n /// @param tickUpper upper tick of the range to be activated\n /// @return position storage ref of the activated position\n function activate(\n LiquidityPosition.Set storage set,\n int24 tickLower,\n int24 tickUpper\n ) internal returns (LiquidityPosition.Info storage position) {\n if (tickLower > tickUpper) {\n revert LPS_IllegalTicks(tickLower, tickUpper);\n }\n\n uint48 positionId;\n set.active.include(positionId = tickLower.concat(tickUpper));\n position = set.positions[positionId];\n\n if (!position.isInitialized()) {\n position.initialize(tickLower, tickUpper);\n }\n }\n\n /// @notice deactivates a position by removing it from the set\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param position storage ref to the position to be deactivated\n function deactivate(LiquidityPosition.Set storage set, LiquidityPosition.Info storage position) internal {\n if (position.liquidity != 0) {\n revert LPS_DeactivationFailed(position.tickLower, position.tickUpper, position.liquidity);\n }\n\n set.active.exclude(position.tickLower.concat(position.tickUpper));\n }\n\n /// @notice changes liquidity of a position in the set\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param accountId serial number of the account\n /// @param poolId truncated address of vToken\n /// @param liquidityChangeParams parameters of the liquidity change\n /// @param balanceAdjustments adjustments to made to the account's balance later\n /// @param protocol ref to the state of the protocol\n function liquidityChange(\n LiquidityPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\n Protocol.Info storage protocol\n ) internal {\n LiquidityPosition.Info storage position = set.activate(\n liquidityChangeParams.tickLower,\n liquidityChangeParams.tickUpper\n );\n\n position.limitOrderType = liquidityChangeParams.limitOrderType;\n\n set.liquidityChange(\n accountId,\n poolId,\n position,\n liquidityChangeParams.liquidityDelta,\n balanceAdjustments,\n protocol\n );\n }\n\n /// @notice changes liquidity of a position in the set\n /// @param accountId serial number of the account\n /// @param poolId truncated address of vToken\n /// @param position storage ref to the position to be changed\n /// @param liquidityDelta amount of liquidity to be added or removed\n /// @param balanceAdjustments adjustments to made to the account's balance later\n /// @param protocol ref to the state of the protocol\n function liquidityChange(\n LiquidityPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n LiquidityPosition.Info storage position,\n int128 liquidityDelta,\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\n Protocol.Info storage protocol\n ) internal {\n position.liquidityChange(accountId, poolId, liquidityDelta, balanceAdjustments, protocol);\n\n emit TokenPositionChangedDueToLiquidityChanged(\n accountId,\n poolId,\n position.tickLower,\n position.tickUpper,\n balanceAdjustments.vTokenIncrease\n );\n\n if (position.liquidity == 0) {\n set.deactivate(position);\n }\n }\n\n /// @notice removes liquidity from a position in the set\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param accountId serial number of the account\n /// @param poolId truncated address of vToken\n /// @param position storage ref to the position to be closed\n /// @param balanceAdjustments adjustments to made to the account's balance later\n /// @param protocol ref to the state of the protocol\n function closeLiquidityPosition(\n LiquidityPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n LiquidityPosition.Info storage position,\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\n Protocol.Info storage protocol\n ) internal {\n set.liquidityChange(accountId, poolId, position, -int128(position.liquidity), balanceAdjustments, protocol);\n }\n\n /// @notice removes liquidity from a position in the set\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param accountId serial number of the account\n /// @param poolId truncated address of vToken\n /// @param currentTick current tick of the pool\n /// @param tickLower lower tick of the range to be closed\n /// @param tickUpper upper tick of the range to be closed\n /// @param balanceAdjustments adjustments to made to the account's balance later\n /// @param protocol ref to the state of the protocol\n function removeLimitOrder(\n LiquidityPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n int24 currentTick,\n int24 tickLower,\n int24 tickUpper,\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\n Protocol.Info storage protocol\n ) internal {\n LiquidityPosition.Info storage position = set.getLiquidityPosition(tickLower, tickUpper);\n position.checkValidLimitOrderRemoval(currentTick);\n set.closeLiquidityPosition(accountId, poolId, position, balanceAdjustments, protocol);\n }\n\n /// @notice removes liquidity from all the positions in the set\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param accountId serial number of the account\n /// @param poolId truncated address of vToken\n /// @param balanceAdjustments adjustments to made to the account's balance later\n /// @param protocol ref to the state of the protocol\n function closeAllLiquidityPositions(\n LiquidityPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\n Protocol.Info storage protocol\n ) internal {\n LiquidityPosition.Info storage position;\n\n while (set.active[0] != 0) {\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustmentsCurrent;\n\n position = set.positions[set.active[0]];\n\n set.closeLiquidityPosition(accountId, poolId, position, balanceAdjustmentsCurrent, protocol);\n\n balanceAdjustments.vQuoteIncrease += balanceAdjustmentsCurrent.vQuoteIncrease;\n balanceAdjustments.vTokenIncrease += balanceAdjustmentsCurrent.vTokenIncrease;\n balanceAdjustments.traderPositionIncrease += balanceAdjustmentsCurrent.traderPositionIncrease;\n }\n }\n\n /**\n * Internal view methods\n */\n\n /// @notice gets the liquidity position of a tick range\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param tickLower lower tick of the range to be closed\n /// @param tickUpper upper tick of the range to be closed\n /// @return position liquidity position of the tick range\n function getLiquidityPosition(\n LiquidityPosition.Set storage set,\n int24 tickLower,\n int24 tickUpper\n ) internal view returns (LiquidityPosition.Info storage position) {\n if (tickLower > tickUpper) {\n revert LPS_IllegalTicks(tickLower, tickUpper);\n }\n\n uint48 positionId = Uint48Lib.concat(tickLower, tickUpper);\n position = set.positions[positionId];\n\n if (!position.isInitialized()) revert LPS_InactiveRange();\n return position;\n }\n\n /// @notice gets information about all the liquidity position\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @return liquidityPositions Information about all the liquidity position for the pool\n function getInfo(LiquidityPosition.Set storage set)\n internal\n view\n returns (IClearingHouseStructures.LiquidityPositionView[] memory liquidityPositions)\n {\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\n liquidityPositions = new IClearingHouseStructures.LiquidityPositionView[](numberOfTokenPositions);\n\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\n liquidityPositions[i].limitOrderType = set.positions[set.active[i]].limitOrderType;\n liquidityPositions[i].tickLower = set.positions[set.active[i]].tickLower;\n liquidityPositions[i].tickUpper = set.positions[set.active[i]].tickUpper;\n liquidityPositions[i].liquidity = set.positions[set.active[i]].liquidity;\n liquidityPositions[i].vTokenAmountIn = set.positions[set.active[i]].vTokenAmountIn;\n liquidityPositions[i].sumALastX128 = set.positions[set.active[i]].sumALastX128;\n liquidityPositions[i].sumBInsideLastX128 = set.positions[set.active[i]].sumBInsideLastX128;\n liquidityPositions[i].sumFpInsideLastX128 = set.positions[set.active[i]].sumFpInsideLastX128;\n liquidityPositions[i].sumFeeInsideLastX128 = set.positions[set.active[i]].sumFeeInsideLastX128;\n }\n }\n\n /// @notice gets the net position due to all the liquidity positions\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param sqrtPriceCurrent current sqrt price of the pool\n /// @return netPosition due to all the liquidity positions\n function getNetPosition(LiquidityPosition.Set storage set, uint160 sqrtPriceCurrent)\n internal\n view\n returns (int256 netPosition)\n {\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\n\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\n netPosition += set.positions[set.active[i]].netPosition(sqrtPriceCurrent);\n }\n }\n\n /// @notice checks whether the liquidity position set is empty\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @return true if the liquidity position set is empty\n function isEmpty(LiquidityPosition.Set storage set) internal view returns (bool) {\n return set.active.isEmpty();\n }\n\n /// @notice checks whether for given ticks, a liquidity position is active\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param tickLower lower tick of the range\n /// @param tickUpper upper tick of the range\n /// @return true if the liquidity position is active\n function isPositionActive(\n LiquidityPosition.Set storage set,\n int24 tickLower,\n int24 tickUpper\n ) internal view returns (bool) {\n return set.active.exists(tickLower.concat(tickUpper));\n }\n\n /// @notice gets the total long side risk for all the active liquidity positions\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param valuationPriceX96 price used to value the vToken asset\n /// @return risk the net long side risk for all the active liquidity positions\n function longSideRisk(LiquidityPosition.Set storage set, uint160 valuationPriceX96)\n internal\n view\n returns (uint256 risk)\n {\n for (uint256 i = 0; i < set.active.length; i++) {\n uint48 id = set.active[i];\n if (id == 0) break;\n risk += set.positions[id].longSideRisk(valuationPriceX96);\n }\n }\n\n /// @notice gets the total market value of all the active liquidity positions\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @param sqrtPriceCurrent price used to value the vToken asset\n /// @param poolId the id of the pool\n /// @param protocol ref to the state of the protocol\n /// @return marketValue_ the total market value of all the active liquidity positions\n function marketValue(\n LiquidityPosition.Set storage set,\n uint160 sqrtPriceCurrent,\n uint32 poolId,\n Protocol.Info storage protocol\n ) internal view returns (int256 marketValue_) {\n marketValue_ = set.marketValue(sqrtPriceCurrent, protocol.vPoolWrapper(poolId));\n }\n\n /// @notice Get the total market value of all active liquidity positions in the set.\n /// @param set: Collection of active liquidity positions\n /// @param sqrtPriceCurrent: Current price of the virtual asset\n /// @param wrapper: address of the wrapper contract, passed once to avoid multiple sloads for wrapper\n function marketValue(\n LiquidityPosition.Set storage set,\n uint160 sqrtPriceCurrent,\n IVPoolWrapper wrapper\n ) internal view returns (int256 marketValue_) {\n for (uint256 i = 0; i < set.active.length; i++) {\n uint48 id = set.active[i];\n if (id == 0) break;\n marketValue_ += set.positions[id].marketValue(sqrtPriceCurrent, wrapper);\n }\n }\n\n /// @notice gets the max net position possible due to all the liquidity positions\n /// @param set storage ref to the account's set of liquidity positions of a pool\n /// @return risk the max net position possible due to all the liquidity positions\n function maxNetPosition(LiquidityPosition.Set storage set) internal view returns (uint256 risk) {\n for (uint256 i = 0; i < set.active.length; i++) {\n uint48 id = set.active[i];\n if (id == 0) break;\n risk += set.positions[id].maxNetPosition();\n }\n }\n}\n" + }, + "contracts/libraries/VTokenPosition.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.4;\n\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { FundingPayment } from './FundingPayment.sol';\nimport { LiquidityPosition } from './LiquidityPosition.sol';\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\nimport { Protocol } from './Protocol.sol';\nimport { SignedFullMath } from './SignedFullMath.sol';\nimport { UniswapV3PoolHelper } from './UniswapV3PoolHelper.sol';\n\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\n\n/// @title VToken position functions\nlibrary VTokenPosition {\n using FullMath for uint256;\n using SignedFullMath for int256;\n using UniswapV3PoolHelper for IUniswapV3Pool;\n\n using LiquidityPosition for LiquidityPosition.Info;\n using LiquidityPositionSet for LiquidityPosition.Set;\n using Protocol for Protocol.Info;\n\n enum RISK_SIDE {\n LONG,\n SHORT\n }\n\n struct Set {\n // Fixed length array of poolId = vTokenAddress.truncate()\n // Open positions in 8 different pairs at same time.\n // Collision between poolId is not possible.\n uint32[8] active; // array of poolIds\n mapping(uint32 => VTokenPosition.Info) positions; // poolId => Position\n int256 vQuoteBalance;\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\n }\n\n struct Info {\n int256 balance; // vTokenLong - vTokenShort\n int256 netTraderPosition;\n int256 sumALastX128;\n // this is moved from accounts to here because of the in margin available check\n // the loop needs to be done over liquidity positions of same token only\n LiquidityPosition.Set liquidityPositions;\n uint256[100] _emptySlots; // reserved for adding variables when upgrading logic\n }\n\n /// @notice Gives the market value of the supplied token position\n /// @param position token position\n /// @param priceX128 price in Q128\n /// @param wrapper pool wrapper corresponding to position\n /// @return value market value with 6 decimals\n function marketValue(\n VTokenPosition.Info storage position,\n uint256 priceX128,\n IVPoolWrapper wrapper\n ) internal view returns (int256 value) {\n value = position.balance.mulDiv(priceX128, FixedPoint128.Q128);\n value += unrealizedFundingPayment(position, wrapper);\n }\n\n /// @notice returns the market value of the supplied token position\n /// @param position token position\n /// @param priceX128 price in Q128\n /// @param poolId id of the rage trade pool\n /// @param protocol ref to the protocol state\n function marketValue(\n VTokenPosition.Info storage position,\n uint32 poolId,\n uint256 priceX128,\n Protocol.Info storage protocol\n ) internal view returns (int256 value) {\n return marketValue(position, priceX128, protocol.vPoolWrapper(poolId));\n }\n\n /// @notice returns the market value of the supplied token position\n /// @param position token position\n /// @param poolId id of the rage trade pool\n /// @param protocol ref to the protocol state\n function marketValue(\n VTokenPosition.Info storage position,\n uint32 poolId,\n Protocol.Info storage protocol\n ) internal view returns (int256) {\n uint256 priceX128 = protocol.getCachedVirtualTwapPriceX128(poolId);\n return marketValue(position, poolId, priceX128, protocol);\n }\n\n function riskSide(VTokenPosition.Info storage position) internal view returns (RISK_SIDE) {\n return position.balance > 0 ? RISK_SIDE.LONG : RISK_SIDE.SHORT;\n }\n\n /// @notice returns the vQuoteIncrease due to unrealized funding payment for the trader position (+ve means receiving and -ve means paying)\n /// @param position token position\n /// @param wrapper pool wrapper corresponding to position\n /// @return unrealizedFpBill funding to be realized (+ve means receive and -ve means pay)\n function unrealizedFundingPayment(VTokenPosition.Info storage position, IVPoolWrapper wrapper)\n internal\n view\n returns (int256)\n {\n int256 extrapolatedSumAX128 = wrapper.getExtrapolatedSumAX128();\n int256 vQuoteIncrease = -FundingPayment.bill(\n extrapolatedSumAX128,\n position.sumALastX128,\n position.netTraderPosition\n );\n return vQuoteIncrease;\n }\n\n /// @notice gets the account's net position for a given poolId\n /// @param position token position\n /// @param poolId id of the rage trade pool\n /// @param protocol ref to the protocol state\n /// @return net position\n function getNetPosition(\n VTokenPosition.Info storage position,\n uint32 poolId,\n Protocol.Info storage protocol\n ) internal view returns (int256) {\n return\n position.netTraderPosition +\n position.liquidityPositions.getNetPosition(protocol.vPool(poolId).sqrtPriceCurrent());\n }\n}\n" + }, + "contracts/libraries/VTokenPositionSet.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.4;\n\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\n\nimport { AddressHelper } from './AddressHelper.sol';\nimport { LiquidityPosition } from './LiquidityPosition.sol';\nimport { LiquidityPositionSet } from './LiquidityPositionSet.sol';\nimport { Protocol } from './Protocol.sol';\nimport { PriceMath } from './PriceMath.sol';\nimport { SignedFullMath } from './SignedFullMath.sol';\nimport { SignedMath } from './SignedMath.sol';\nimport { VTokenPosition } from './VTokenPosition.sol';\nimport { Uint32L8ArrayLib } from './Uint32L8Array.sol';\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\n\n/// @title VToken position set functions\nlibrary VTokenPositionSet {\n using AddressHelper for address;\n using FullMath for uint256;\n using PriceMath for uint256;\n using SafeCast for uint256;\n using SignedFullMath for int256;\n using SignedMath for int256;\n using Uint32L8ArrayLib for uint32[8];\n\n using LiquidityPositionSet for LiquidityPosition.Set;\n using Protocol for Protocol.Info;\n using VTokenPosition for VTokenPosition.Info;\n using VTokenPositionSet for VTokenPosition.Set;\n\n error VPS_IncorrectUpdate();\n error VPS_DeactivationFailed(uint32 poolId);\n error VPS_TokenInactive(uint32 poolId);\n\n /// @notice denotes token position change\n /// @param accountId serial number of the account\n /// @param poolId truncated address of vtoken whose position was taken\n /// @param vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\n /// @param vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\n /// @param sqrtPriceX96Start shows the sqrtPriceX96 at the start of trade execution, can be 0 if not on v3Pool\n /// @param sqrtPriceX96End shows the sqrtPriceX96 at the end of trade execution, can be 0 if not on v3Pool\n event TokenPositionChanged(\n uint256 indexed accountId,\n uint32 indexed poolId,\n int256 vTokenAmountOut,\n int256 vQuoteAmountOut,\n uint160 sqrtPriceX96Start,\n uint160 sqrtPriceX96End\n );\n\n /// @notice denotes funding payment for a range / token position\n /// @param accountId serial number of the account\n /// @param poolId address of token for which funding was paid\n /// @param amount amount of funding paid (negative) or received (positive)\n /// @param sumALastX128 val of sum of the term A in funding payment math, when op took place\n event TokenPositionFundingPaymentRealized(\n uint256 indexed accountId,\n uint32 indexed poolId,\n int256 amount,\n int256 sumALastX128\n );\n\n /**\n * Internal methods\n */\n\n /// @notice activates token with address 'vToken' if not already active\n /// @param set VTokenPositionSet\n /// @param poolId id of the rage trade pool\n function activate(VTokenPosition.Set storage set, uint32 poolId) internal {\n set.active.include(poolId);\n }\n\n /// @notice deactivates token with address 'vToken'\n /// @dev ensures that the balance is 0 and there are not range positions active otherwise throws an error\n /// @param set VTokenPositionSet\n /// @param poolId id of the rage trade pool\n function deactivate(VTokenPosition.Set storage set, uint32 poolId) internal {\n if (set.positions[poolId].balance != 0 || !set.positions[poolId].liquidityPositions.isEmpty()) {\n revert VPS_DeactivationFailed(poolId);\n }\n\n set.active.exclude(poolId);\n }\n\n /// @notice updates token balance, net trader position and vQuote balance\n /// @dev realizes funding payment to vQuote balance\n /// @dev activates the token if not already active\n /// @dev deactivates the token if the balance = 0 and there are no range positions active\n /// @dev IMP: ensure that the global states are updated using zeroSwap or directly through some interaction with pool wrapper\n /// @param set VTokenPositionSet\n /// @param balanceAdjustments platform constants\n /// @param poolId id of the rage trade pool\n /// @param accountId account identifier, used for emitting event\n /// @param protocol platform constants\n function update(\n VTokenPosition.Set storage set,\n uint256 accountId,\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments,\n uint32 poolId,\n Protocol.Info storage protocol\n ) internal {\n set.realizeFundingPayment(accountId, poolId, protocol);\n set.active.include(poolId);\n\n VTokenPosition.Info storage _VTokenPosition = set.positions[poolId];\n _VTokenPosition.balance += balanceAdjustments.vTokenIncrease;\n _VTokenPosition.netTraderPosition += balanceAdjustments.traderPositionIncrease;\n\n set.vQuoteBalance += balanceAdjustments.vQuoteIncrease;\n\n if (_VTokenPosition.balance == 0 && _VTokenPosition.liquidityPositions.active[0] == 0) {\n set.deactivate(poolId);\n }\n }\n\n /// @notice realizes funding payment to vQuote balance\n /// @param set VTokenPositionSet\n /// @param poolId id of the rage trade pool\n /// @param accountId account identifier, used for emitting event\n /// @param protocol platform constants\n function realizeFundingPayment(\n VTokenPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n Protocol.Info storage protocol\n ) internal {\n set.realizeFundingPayment(accountId, poolId, protocol.pools[poolId].vPoolWrapper);\n }\n\n /// @notice realizes funding payment to vQuote balance\n /// @param set VTokenPositionSet\n /// @param poolId id of the rage trade pool\n /// @param accountId account identifier, used for emitting event\n /// @param wrapper VPoolWrapper to override the set wrapper\n function realizeFundingPayment(\n VTokenPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n IVPoolWrapper wrapper\n ) internal {\n VTokenPosition.Info storage position = set.positions[poolId];\n int256 extrapolatedSumAX128 = wrapper.getSumAX128();\n\n int256 fundingPayment = position.unrealizedFundingPayment(wrapper);\n set.vQuoteBalance += fundingPayment;\n\n position.sumALastX128 = extrapolatedSumAX128;\n\n emit TokenPositionFundingPaymentRealized(accountId, poolId, fundingPayment, extrapolatedSumAX128);\n }\n\n /// @notice swaps tokens (Long and Short) with input in token amount / vQuote amount\n /// @param set VTokenPositionSet\n /// @param accountId account identifier, used for emitting event\n /// @param poolId id of the rage trade pool\n /// @param swapParams parameters for swap\n /// @param protocol platform constants\n /// @return vTokenAmountOut - token amount coming out of pool\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\n function swapToken(\n VTokenPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n IClearingHouseStructures.SwapParams memory swapParams,\n Protocol.Info storage protocol\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n return set.swapToken(accountId, poolId, swapParams, protocol.vPoolWrapper(poolId), protocol);\n }\n\n /// @notice swaps tokens (Long and Short) with input in token amount\n /// @dev activates inactive vToe\n /// @param set VTokenPositionSet\n /// @param accountId account identifier, used for emitting event\n /// @param poolId id of the rage trade pool\n /// @param vTokenAmount amount of the token\n /// @param protocol platform constants\n /// @return vTokenAmountOut - token amount coming out of pool\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\n function swapTokenAmount(\n VTokenPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n int256 vTokenAmount,\n Protocol.Info storage protocol\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n return\n set.swapToken(\n accountId,\n poolId,\n /// @dev 0 means no price limit and false means amount mentioned is token amount\n IClearingHouseStructures.SwapParams({\n amount: vTokenAmount,\n sqrtPriceLimit: 0,\n isNotional: false,\n isPartialAllowed: false,\n settleProfit: false\n }),\n protocol.vPoolWrapper(poolId),\n protocol\n );\n }\n\n /// @notice swaps tokens (Long and Short) with input in token amount / vQuote amount\n /// @param set VTokenPositionSet\n /// @param accountId account identifier, used for emitting event\n /// @param poolId id of the rage trade pool\n /// @param swapParams parameters for swap\n /// @param wrapper VPoolWrapper to override the set wrapper\n /// @param protocol platform constants\n /// @return vTokenAmountOut - token amount coming out of pool\n /// @return vQuoteAmountOut - vQuote amount coming out of pool\n function swapToken(\n VTokenPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n IClearingHouseStructures.SwapParams memory swapParams,\n IVPoolWrapper wrapper,\n Protocol.Info storage protocol\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n IVPoolWrapper.SwapResult memory swapResult = wrapper.swap(\n swapParams.amount < 0,\n swapParams.isNotional ? swapParams.amount : -swapParams.amount,\n swapParams.sqrtPriceLimit\n );\n\n // change direction basis uniswap to balance increase\n vTokenAmountOut = -swapResult.vTokenIn;\n vQuoteAmountOut = -swapResult.vQuoteIn;\n\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments = IClearingHouseStructures\n .BalanceAdjustments(vQuoteAmountOut, vTokenAmountOut, vTokenAmountOut);\n\n set.update(accountId, balanceAdjustments, poolId, protocol);\n\n emit TokenPositionChanged(\n accountId,\n poolId,\n vTokenAmountOut,\n vQuoteAmountOut,\n swapResult.sqrtPriceX96Start,\n swapResult.sqrtPriceX96End\n );\n }\n\n /// @notice function to liquidate all liquidity positions\n /// @param set VTokenPositionSet\n /// @param accountId account identifier, used for emitting event\n /// @param protocol platform constants\n /// @return notionalAmountClosed - value of net token position coming out (in notional) of all the ranges closed\n function liquidateLiquidityPositions(\n VTokenPosition.Set storage set,\n uint256 accountId,\n Protocol.Info storage protocol\n ) internal returns (uint256 notionalAmountClosed) {\n for (uint8 i = 0; i < set.active.length; i++) {\n uint32 truncated = set.active[i];\n if (truncated == 0) break;\n\n notionalAmountClosed += set.liquidateLiquidityPositions(accountId, set.active[i], protocol);\n }\n }\n\n /// @notice function to liquidate liquidity positions for a particular token\n /// @param set VTokenPositionSet\n /// @param accountId account identifier, used for emitting event\n /// @param poolId id of the rage trade pool\n /// @param protocol platform constants\n /// @return notionalAmountClosed - value of net token position coming out (in notional) of all the ranges closed\n function liquidateLiquidityPositions(\n VTokenPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n Protocol.Info storage protocol\n ) internal returns (uint256 notionalAmountClosed) {\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\n\n set.getTokenPosition(poolId, false).liquidityPositions.closeAllLiquidityPositions(\n accountId,\n poolId,\n balanceAdjustments,\n protocol\n );\n\n set.update(accountId, balanceAdjustments, poolId, protocol);\n\n // returns notional value of token position closed\n return protocol.getNotionalValue(poolId, balanceAdjustments.traderPositionIncrease);\n }\n\n /// @notice function for liquidity add/remove\n /// @param set VTokenPositionSet\n /// @param accountId account identifier, used for emitting event\n /// @param poolId id of the rage trade pool\n /// @param liquidityChangeParams includes tickLower, tickUpper, liquidityDelta, limitOrderType\n /// @return vTokenAmountOut amount of tokens that account received (positive) or paid (negative)\n /// @return vQuoteAmountOut amount of vQuote tokens that account received (positive) or paid (negative)\n function liquidityChange(\n VTokenPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams,\n Protocol.Info storage protocol\n ) internal returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, true);\n\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\n\n vTokenPosition.liquidityPositions.liquidityChange(\n accountId,\n poolId,\n liquidityChangeParams,\n balanceAdjustments,\n protocol\n );\n\n set.update(accountId, balanceAdjustments, poolId, protocol);\n\n if (liquidityChangeParams.closeTokenPosition && balanceAdjustments.traderPositionIncrease != 0) {\n set.swapTokenAmount(accountId, poolId, -balanceAdjustments.traderPositionIncrease, protocol);\n }\n\n return (balanceAdjustments.vTokenIncrease, balanceAdjustments.vQuoteIncrease);\n }\n\n /// @notice function to remove an eligible limit order\n /// @dev checks whether the current price is on the correct side of the range based on the type of limit order (None, Low, High)\n /// @param set VTokenPositionSet\n /// @param accountId account identifier, used for emitting event\n /// @param poolId id of the rage trade pool\n /// @param tickLower lower tick index for the range\n /// @param tickUpper upper tick index for the range\n /// @param protocol platform constants\n function removeLimitOrder(\n VTokenPosition.Set storage set,\n uint256 accountId,\n uint32 poolId,\n int24 tickLower,\n int24 tickUpper,\n Protocol.Info storage protocol\n ) internal {\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, false);\n\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\n int24 currentTick = protocol.getVirtualCurrentTick(poolId);\n\n vTokenPosition.liquidityPositions.removeLimitOrder(\n accountId,\n poolId,\n currentTick,\n tickLower,\n tickUpper,\n balanceAdjustments,\n protocol\n );\n\n set.update(accountId, balanceAdjustments, poolId, protocol);\n }\n\n function updateOpenPoolPrices(VTokenPosition.Set storage set, Protocol.Info storage protocol) internal {\n for (uint8 i = 0; i < set.active.length; i++) {\n uint32 poolId = set.active[i];\n if (poolId == 0) break;\n protocol.updatePoolPriceCache(poolId);\n }\n }\n\n /**\n * Internal view methods\n */\n\n /// @notice returns account market value of active positions\n /// @param set VTokenPositionSet\n /// @param protocol platform constants\n /// @return accountMarketValue - value of all active positions\n function getAccountMarketValue(VTokenPosition.Set storage set, Protocol.Info storage protocol)\n internal\n view\n returns (int256 accountMarketValue)\n {\n for (uint8 i = 0; i < set.active.length; i++) {\n uint32 poolId = set.active[i];\n if (poolId == 0) break;\n // IVToken vToken = protocol[poolId].vToken;\n VTokenPosition.Info storage position = set.positions[poolId];\n\n (, uint256 virtualPriceX128) = protocol.getCachedTwapPricesWithDeviationCheck(poolId);\n uint160 virtualSqrtPriceX96 = virtualPriceX128.toSqrtPriceX96();\n //Value of token position for current vToken\n accountMarketValue += position.marketValue(poolId, virtualPriceX128, protocol);\n\n //Value of all active range position for the current vToken\n accountMarketValue += position.liquidityPositions.marketValue(virtualSqrtPriceX96, poolId, protocol);\n }\n\n // Value of the vQuote token balance\n accountMarketValue += set.vQuoteBalance;\n }\n\n /// @notice gets information about the token and liquidity positions for all the pools\n /// @param set VTokenPositionSet\n /// @return vQuoteBalance vQuote balance for the token position\n /// @return vTokenPositions array of vToken position\n function getInfo(VTokenPosition.Set storage set)\n internal\n view\n returns (int256 vQuoteBalance, IClearingHouseStructures.VTokenPositionView[] memory vTokenPositions)\n {\n vQuoteBalance = set.vQuoteBalance;\n\n uint256 numberOfTokenPositions = set.active.numberOfNonZeroElements();\n vTokenPositions = new IClearingHouseStructures.VTokenPositionView[](numberOfTokenPositions);\n\n for (uint256 i = 0; i < numberOfTokenPositions; i++) {\n vTokenPositions[i].poolId = set.active[i];\n vTokenPositions[i].balance = set.positions[set.active[i]].balance;\n vTokenPositions[i].netTraderPosition = set.positions[set.active[i]].netTraderPosition;\n vTokenPositions[i].sumALastX128 = set.positions[set.active[i]].sumALastX128;\n vTokenPositions[i].liquidityPositions = set.positions[set.active[i]].liquidityPositions.getInfo();\n }\n }\n\n /// @notice returns the long and short side risk for range positions of a particular token\n /// @param set VTokenPositionSet\n /// @param isInitialMargin specifies to use initial margin factor (true) or maintainance margin factor (false)\n /// @param poolId id of the rage trade pool\n /// @param protocol platform constants\n /// @return longSideRisk - risk if the token price goes down\n /// @return shortSideRisk - risk if the token price goes up\n function getLongShortSideRisk(\n VTokenPosition.Set storage set,\n bool isInitialMargin,\n uint32 poolId,\n Protocol.Info storage protocol\n ) internal view returns (int256 longSideRisk, int256 shortSideRisk) {\n VTokenPosition.Info storage position = set.positions[poolId];\n\n (, uint256 virtualPriceX128) = protocol.getCachedTwapPricesWithDeviationCheck(poolId);\n uint160 virtualSqrtPriceX96 = virtualPriceX128.toSqrtPriceX96();\n\n uint16 marginRatio = protocol.getMarginRatioBps(poolId, isInitialMargin);\n\n int256 tokenPosition = position.balance;\n int256 longSideRiskRanges = position.liquidityPositions.longSideRisk(virtualSqrtPriceX96).toInt256();\n\n longSideRisk = SignedMath\n .max(position.netTraderPosition.mulDiv(virtualPriceX128, FixedPoint128.Q128) + longSideRiskRanges, 0)\n .mulDiv(marginRatio, 1e4);\n\n shortSideRisk = SignedMath.max(-tokenPosition, 0).mulDiv(virtualPriceX128, FixedPoint128.Q128).mulDiv(\n marginRatio,\n 1e4\n );\n return (longSideRisk, shortSideRisk);\n }\n\n /// @notice gets the net position for the given poolId\n /// @param set VTokenPositionSet\n /// @param poolId id of the rage trade pool\n /// @param protocol platform constants\n /// @return netPosition net position of the account for the pool\n function getNetPosition(\n VTokenPosition.Set storage set,\n uint32 poolId,\n Protocol.Info storage protocol\n ) internal view returns (int256 netPosition) {\n if (!set.active.exists(poolId)) return 0;\n VTokenPosition.Info storage tokenPosition = set.positions[poolId];\n return tokenPosition.getNetPosition(poolId, protocol);\n }\n\n /// @notice returns the long and short side risk for range positions of a particular token\n /// @param set VTokenPositionSet\n /// @param isInitialMargin specifies to use initial margin factor (true) or maintainance margin factor (false)\n /// @param protocol platform constants\n /// @return requiredMargin - required margin value based on the current active positions\n function getRequiredMargin(\n VTokenPosition.Set storage set,\n bool isInitialMargin,\n Protocol.Info storage protocol\n ) internal view returns (int256 requiredMargin) {\n int256 longSideRiskTotal;\n int256 shortSideRiskTotal;\n int256 longSideRisk;\n int256 shortSideRisk;\n for (uint8 i = 0; i < set.active.length; i++) {\n if (set.active[i] == 0) break;\n uint32 poolId = set.active[i];\n (longSideRisk, shortSideRisk) = set.getLongShortSideRisk(isInitialMargin, poolId, protocol);\n\n if (protocol.isPoolCrossMargined(poolId)) {\n longSideRiskTotal += longSideRisk;\n shortSideRiskTotal += shortSideRisk;\n } else {\n requiredMargin += SignedMath.max(longSideRisk, shortSideRisk);\n }\n }\n\n requiredMargin += SignedMath.max(longSideRiskTotal, shortSideRiskTotal);\n }\n\n /// @notice get or create token position\n /// @dev activates inactive vToken if isCreateNew is true else reverts\n /// @param set VTokenPositionSet\n /// @param poolId id of the rage trade pool\n /// @param createNew if 'vToken' is inactive then activates (true) else reverts with TokenInactive(false)\n /// @return position - VTokenPosition corresponding to 'vToken'\n function getTokenPosition(\n VTokenPosition.Set storage set,\n uint32 poolId,\n bool createNew\n ) internal returns (VTokenPosition.Info storage position) {\n if (createNew) {\n set.activate(poolId);\n } else if (!set.active.exists(poolId)) {\n revert VPS_TokenInactive(poolId);\n }\n\n position = set.positions[poolId];\n }\n\n /// @notice returns true if the set does not have any token position active\n /// @param set VTokenPositionSet\n /// @return True if there are no active positions\n function isEmpty(VTokenPosition.Set storage set) internal view returns (bool) {\n return set.active.isEmpty();\n }\n\n /// @notice returns true if range position is active for 'vToken'\n /// @param set VTokenPositionSet\n /// @param poolId poolId of the vToken\n /// @return isRangeActive - True if the range position is active\n function isTokenRangeActive(VTokenPosition.Set storage set, uint32 poolId) internal returns (bool isRangeActive) {\n VTokenPosition.Info storage vTokenPosition = set.getTokenPosition(poolId, false);\n isRangeActive = !vTokenPosition.liquidityPositions.isEmpty();\n }\n}\n" + }, + "contracts/libraries/Uint32L8Array.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\n\n/// @title Uint32 length 8 array functions\n/// @dev Fits in one storage slot\nlibrary Uint32L8ArrayLib {\n using Uint32L8ArrayLib for uint32[8];\n\n uint8 constant LENGTH = 8;\n\n error U32L8_IllegalElement(uint32 element);\n error U32L8_NoSpaceLeftToInsert(uint32 element);\n\n /// @notice Inserts an element in the array\n /// @dev Replaces a zero value in the array with element\n /// @param array Array to modify\n /// @param element Element to insert\n function include(uint32[8] storage array, uint32 element) internal {\n if (element == 0) {\n revert U32L8_IllegalElement(0);\n }\n\n uint256 emptyIndex = LENGTH; // LENGTH is an invalid index\n for (uint256 i; i < LENGTH; i++) {\n if (array[i] == element) {\n // if element already exists in the array, do nothing\n return;\n }\n // if we found an empty slot, remember it\n if (array[i] == uint32(0)) {\n emptyIndex = i;\n break;\n }\n }\n\n // if empty index is still LENGTH, there is no space left to insert\n if (emptyIndex == LENGTH) {\n revert U32L8_NoSpaceLeftToInsert(element);\n }\n\n array[emptyIndex] = element;\n }\n\n /// @notice Excludes the element from the array\n /// @dev If element exists, it swaps with last element and makes last element zero\n /// @param array Array to modify\n /// @param element Element to remove\n function exclude(uint32[8] storage array, uint32 element) internal {\n if (element == 0) {\n revert U32L8_IllegalElement(0);\n }\n\n uint256 elementIndex = LENGTH; // LENGTH is an invalid index\n uint256 i;\n\n for (; i < LENGTH; i++) {\n if (array[i] == element) {\n // element index in the array\n elementIndex = i;\n }\n if (array[i] == 0) {\n // last non-zero element\n i = i > 0 ? i - 1 : 0;\n break;\n }\n }\n\n // if array is full, i == LENGTH\n // hence swapping with element at last index\n i = i == LENGTH ? LENGTH - 1 : i;\n\n if (elementIndex != LENGTH) {\n if (i == elementIndex) {\n // if element is last element, simply make it zero\n array[elementIndex] = 0;\n } else {\n // move last to element's place and empty lastIndex slot\n (array[elementIndex], array[i]) = (array[i], 0);\n }\n }\n }\n\n /// @notice Returns the index of the element in the array\n /// @param array Array to perform search on\n /// @param element Element to search\n /// @return index if exists or LENGTH otherwise\n function indexOf(uint32[8] storage array, uint32 element) internal view returns (uint8) {\n for (uint8 i; i < LENGTH; i++) {\n if (array[i] == element) {\n return i;\n }\n }\n return LENGTH; // LENGTH is an invalid index\n }\n\n /// @notice Checks whether the element exists in the array\n /// @param array Array to perform search on\n /// @param element Element to search\n /// @return True if element is found, false otherwise\n function exists(uint32[8] storage array, uint32 element) internal view returns (bool) {\n return array.indexOf(element) != LENGTH; // LENGTH is an invalid index\n }\n\n /// @notice Returns length of array (number of non-zero elements)\n /// @param array Array to perform search on\n /// @return Length of array\n function numberOfNonZeroElements(uint32[8] storage array) internal view returns (uint256) {\n for (uint8 i; i < LENGTH; i++) {\n if (array[i] == 0) {\n return i;\n }\n }\n return LENGTH;\n }\n\n /// @notice Checks whether the array is empty or not\n /// @param array Array to perform search on\n /// @return True if the set does not have any token position active\n function isEmpty(uint32[8] storage array) internal view returns (bool) {\n return array[0] == 0;\n }\n}\n" + }, + "contracts/libraries/Uint48L5Array.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\n\n/// @title Uint48 length 5 array functions\n/// @dev Fits in one storage slot\nlibrary Uint48L5ArrayLib {\n using Uint48L5ArrayLib for uint48[5];\n\n uint8 constant LENGTH = 5;\n\n error U48L5_IllegalElement(uint48 element);\n error U48L5_NoSpaceLeftToInsert(uint48 element);\n\n /// @notice Inserts an element in the array\n /// @dev Replaces a zero value in the array with element\n /// @param array Array to modify\n /// @param element Element to insert\n function include(uint48[5] storage array, uint48 element) internal {\n if (element == 0) {\n revert U48L5_IllegalElement(0);\n }\n\n uint256 emptyIndex = LENGTH; // LENGTH is an invalid index\n for (uint256 i; i < LENGTH; i++) {\n if (array[i] == element) {\n // if element already exists in the array, do nothing\n return;\n }\n // if we found an empty slot, remember it\n if (array[i] == uint48(0)) {\n emptyIndex = i;\n break;\n }\n }\n\n // if empty index is still LENGTH, there is no space left to insert\n if (emptyIndex == LENGTH) {\n revert U48L5_NoSpaceLeftToInsert(element);\n }\n\n array[emptyIndex] = element;\n }\n\n /// @notice Excludes the element from the array\n /// @dev If element exists, it swaps with last element and makes last element zero\n /// @param array Array to modify\n /// @param element Element to remove\n function exclude(uint48[5] storage array, uint48 element) internal {\n if (element == 0) {\n revert U48L5_IllegalElement(0);\n }\n\n uint256 elementIndex = LENGTH; // LENGTH is an invalid index\n uint256 i;\n\n for (; i < LENGTH; i++) {\n if (array[i] == element) {\n // element index in the array\n elementIndex = i;\n }\n if (array[i] == 0) {\n // last non-zero element\n i = i > 0 ? i - 1 : 0;\n break;\n }\n }\n\n // if array is full, i == LENGTH\n // hence swapping with element at last index\n i = i == LENGTH ? LENGTH - 1 : i;\n\n if (elementIndex != LENGTH) {\n if (i == elementIndex) {\n // if element is last element, simply make it zero\n array[elementIndex] = 0;\n } else {\n // move last to element's place and empty lastIndex slot\n (array[elementIndex], array[i]) = (array[i], 0);\n }\n }\n }\n\n /// @notice Returns the index of the element in the array\n /// @param array Array to perform search on\n /// @param element Element to search\n /// @return index if exists or LENGTH otherwise\n function indexOf(uint48[5] storage array, uint48 element) internal view returns (uint8) {\n for (uint8 i; i < LENGTH; i++) {\n if (array[i] == element) {\n return i;\n }\n }\n return LENGTH; // LENGTH is an invalid index\n }\n\n /// @notice Checks whether the element exists in the array\n /// @param array Array to perform search on\n /// @param element Element to search\n /// @return True if element is found, false otherwise\n function exists(uint48[5] storage array, uint48 element) internal view returns (bool) {\n return array.indexOf(element) != LENGTH; // LENGTH is an invalid index\n }\n\n /// @notice Returns length of array (number of non-zero elements)\n /// @param array Array to perform search on\n /// @return Length of array\n function numberOfNonZeroElements(uint48[5] storage array) internal view returns (uint256) {\n for (uint8 i; i < LENGTH; i++) {\n if (array[i] == 0) {\n return i;\n }\n }\n return LENGTH;\n }\n\n /// @notice Checks whether the array is empty or not\n /// @param array Array to perform search on\n /// @return True if the set does not have any token position active\n function isEmpty(uint48[5] storage array) internal view returns (bool) {\n return array[0] == 0;\n }\n}\n" + }, + "contracts/test/VTokenPositionSetTest2.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Account } from '../libraries/Account.sol';\nimport { AddressHelper } from '../libraries/AddressHelper.sol';\nimport { LiquidityPosition } from '../libraries/LiquidityPosition.sol';\nimport { LiquidityPositionSet } from '../libraries/LiquidityPositionSet.sol';\nimport { VTokenPosition } from '../libraries/VTokenPosition.sol';\nimport { VTokenPositionSet } from '../libraries/VTokenPositionSet.sol';\nimport { Uint32L8ArrayLib } from '../libraries/Uint32L8Array.sol';\n\nimport { IVToken } from '../interfaces/IVToken.sol';\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\n\nimport { AccountProtocolInfoMock } from './mocks/AccountProtocolInfoMock.sol';\n\ncontract VTokenPositionSetTest2 is AccountProtocolInfoMock {\n using Uint32L8ArrayLib for uint32[8];\n using AddressHelper for address;\n using AddressHelper for IVToken;\n\n using LiquidityPositionSet for LiquidityPosition.Set;\n using VTokenPositionSet for VTokenPosition.Set;\n\n VTokenPosition.Set dummy;\n\n uint256 accountId = 123;\n\n function init(IVToken vToken) external {\n dummy.activate(vToken.truncate());\n protocol.pools[vToken.truncate()].vToken = vToken;\n }\n\n function update(IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments, IVToken vToken) external {\n dummy.update(accountId, balanceAdjustments, vToken.truncate(), protocol);\n }\n\n function swap(IVToken vToken, IClearingHouseStructures.SwapParams memory swapParams) external {\n dummy.swapToken(accountId, vToken.truncate(), swapParams, protocol);\n }\n\n function liquidityChange(\n IVToken vToken,\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams\n ) external {\n dummy.liquidityChange(accountId, vToken.truncate(), liquidityChangeParams, protocol);\n }\n\n function getAllTokenPositionValue() external view returns (int256) {\n return dummy.getAccountMarketValue(protocol);\n }\n\n function getRequiredMargin(bool isInititalMargin) external view returns (int256) {\n return dummy.getRequiredMargin(isInititalMargin, protocol);\n }\n}\n" + }, + "contracts/test/WordHelperTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\n\nimport { WordHelper } from '../libraries/WordHelper.sol';\n\ncontract WordHelperTest {\n function keccak256One(bytes32 input) public pure returns (bytes32 result) {\n return WordHelper.keccak256One(input);\n }\n\n function keccak256Two(bytes32 input1, bytes32 input2) public pure returns (bytes32 result) {\n return WordHelper.keccak256Two(input1, input2);\n }\n\n function slice(\n bytes32 input,\n uint256 start,\n uint256 end\n ) public pure returns (bytes32 val) {\n return WordHelper.slice(input, start, end);\n }\n\n function offset(bytes32 key, uint256 offset_) public pure returns (bytes32) {\n return WordHelper.offset(key, offset_);\n }\n\n function pop(bytes32 input, uint256 bits) public pure returns (uint256 value, bytes32 inputUpdated) {\n return WordHelper.pop(input, bits);\n }\n\n function popAddress(bytes32 input) public pure returns (address value, bytes32 inputUpdated) {\n (value, inputUpdated) = WordHelper.popAddress(input);\n }\n\n function popUint8(bytes32 input) public pure returns (uint8 value, bytes32 inputUpdated) {\n (value, inputUpdated) = WordHelper.popUint8(input);\n }\n\n function popUint16(bytes32 input) public pure returns (uint16 value, bytes32 inputUpdated) {\n (value, inputUpdated) = WordHelper.popUint16(input);\n }\n\n function popUint32(bytes32 input) public pure returns (uint32 value, bytes32 inputUpdated) {\n (value, inputUpdated) = WordHelper.popUint32(input);\n }\n\n function popUint64(bytes32 input) public pure returns (uint64 value, bytes32 inputUpdated) {\n (value, inputUpdated) = WordHelper.popUint64(input);\n }\n\n function popUint128(bytes32 input) public pure returns (uint128 value, bytes32 inputUpdated) {\n (value, inputUpdated) = WordHelper.popUint128(input);\n }\n\n function popBool(bytes32 input) public pure returns (bool value, bytes32 inputUpdated) {\n (value, inputUpdated) = WordHelper.popBool(input);\n }\n\n function convertToUint32Array(bytes32 active) external pure returns (uint32[] memory activeArr) {\n return WordHelper.convertToUint32Array(active);\n }\n\n function convertToTickRangeArray(bytes32 active)\n external\n view\n returns (IClearingHouseStructures.TickRange[] memory activeArr)\n {\n return WordHelper.convertToTickRangeArray(active);\n }\n}\n" + }, + "contracts/test/Uint48Test.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Uint48Lib } from '../libraries/Uint48.sol';\n\ncontract Uint48Test {\n function assertConcat(int24 val1, int24 val2) external pure returns (uint48 concatenated) {\n concatenated = concat(val1, val2);\n (int24 val1_, int24 val2_) = Uint48Lib.unconcat(concatenated);\n assert(val1_ == val1);\n assert(val2_ == val2);\n }\n\n function concat(int24 val1, int24 val2) public pure returns (uint48 concatenated) {\n concatenated = Uint48Lib.concat(val1, val2);\n }\n}\n" + }, + "contracts/test/VTokenPositionSetTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { VTokenPositionSet } from '../libraries/VTokenPositionSet.sol';\nimport { VTokenPosition } from '../libraries/VTokenPosition.sol';\nimport { LiquidityPosition } from '../libraries/LiquidityPosition.sol';\nimport { LiquidityPositionSet } from '../libraries/LiquidityPositionSet.sol';\nimport { AddressHelper } from '../libraries/AddressHelper.sol';\nimport { Uint32L8ArrayLib } from '../libraries/Uint32L8Array.sol';\nimport { Account } from '../libraries/Account.sol';\n\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\n\nimport { AccountProtocolInfoMock } from './mocks/AccountProtocolInfoMock.sol';\nimport { VPoolWrapperMock } from './mocks/VPoolWrapperMock.sol';\n\ncontract VTokenPositionSetTest is AccountProtocolInfoMock {\n using AddressHelper for address;\n using AddressHelper for IVToken;\n using Uint32L8ArrayLib for uint32[8];\n\n using LiquidityPositionSet for LiquidityPosition.Set;\n using VTokenPositionSet for VTokenPosition.Set;\n\n mapping(uint32 => IVToken) vTokens;\n VTokenPosition.Set dummy;\n\n VPoolWrapperMock public wrapper;\n\n uint256 accountId = 123;\n\n constructor() {\n wrapper = new VPoolWrapperMock();\n }\n\n function init(IVToken vToken) external {\n VTokenPositionSet.activate(dummy, vToken.truncate());\n vTokens[vToken.truncate()] = vToken;\n wrapper.setLiquidityRates(-100, 100, 4000, 1);\n wrapper.setLiquidityRates(-50, 50, 4000, 1);\n }\n\n function update(IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments, IVToken vToken) external {\n dummy.update(accountId, balanceAdjustments, vToken.truncate(), protocol);\n }\n\n function realizeFundingPaymentToAccount(IVToken vToken) external {\n dummy.realizeFundingPayment(accountId, vToken.truncate(), wrapper);\n }\n\n function swapTokenAmount(IVToken vToken, int256 vTokenAmount) external {\n dummy.swapToken(\n accountId,\n vToken.truncate(),\n IClearingHouseStructures.SwapParams(vTokenAmount, 0, false, false, false),\n wrapper,\n protocol\n );\n }\n\n function swapTokenNotional(IVToken vToken, int256 vTokenNotional) external {\n dummy.swapToken(\n accountId,\n vToken.truncate(),\n IClearingHouseStructures.SwapParams(vTokenNotional, 0, true, false, false),\n wrapper,\n protocol\n );\n }\n\n function liquidityChange(\n IVToken vToken,\n int24 tickLower,\n int24 tickUpper,\n int128 liquidity\n ) external {\n // overriding the wrapper to use the mock\n protocol.pools[vToken.truncate()].vPoolWrapper = wrapper;\n\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams = IClearingHouseStructures\n .LiquidityChangeParams(\n tickLower,\n tickUpper,\n liquidity,\n 0,\n 0,\n false,\n IClearingHouseEnums.LimitOrderType.NONE,\n false\n );\n dummy.liquidityChange(accountId, vToken.truncate(), liquidityChangeParams, protocol);\n }\n\n function liquidateLiquidityPositions(IVToken vToken) external {\n dummy.liquidateLiquidityPositions(vToken.truncate(), protocol);\n }\n\n function getIsActive(address vToken) external view returns (bool) {\n return dummy.active.exists(vToken.truncate());\n }\n\n function getPositionDetails(IVToken vToken)\n external\n view\n returns (\n int256 balance,\n int256 sumALastX128,\n int256 netTraderPosition\n )\n {\n VTokenPosition.Info storage pos = dummy.positions[vToken.truncate()];\n return (pos.balance, pos.sumALastX128, pos.netTraderPosition);\n }\n\n function getVQuoteBalance() external view returns (int256 balance) {\n return dummy.vQuoteBalance;\n }\n}\n" + }, + "contracts/test/VTokenPositionTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { VTokenPosition } from '../libraries/VTokenPosition.sol';\n\nimport { IVToken } from '../interfaces/IVToken.sol';\n\nimport { VPoolWrapperMock } from './mocks/VPoolWrapperMock.sol';\n\ncontract VTokenPositionTest {\n using VTokenPosition for VTokenPosition.Info;\n\n uint256 num;\n mapping(uint256 => VTokenPosition.Info) internal dummys;\n\n VPoolWrapperMock public wrapper;\n\n constructor() {\n wrapper = new VPoolWrapperMock();\n }\n\n function init(\n int256 _balance,\n int256 _netTraderPosition,\n int256 _sumALastX128\n ) external {\n VTokenPosition.Info storage dummy = dummys[num++];\n dummy.balance = _balance;\n dummy.netTraderPosition = _netTraderPosition;\n dummy.sumALastX128 = _sumALastX128;\n }\n\n function marketValue(uint256 price) external view returns (int256 value) {\n return dummys[0].marketValue(price, wrapper);\n }\n\n function riskSide() external view returns (uint8) {\n return uint8(dummys[0].riskSide());\n }\n\n function unrealizedFundingPayment() external view returns (int256) {\n return dummys[0].unrealizedFundingPayment(wrapper);\n }\n}\n" + }, + "contracts/test/TickExtendedTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { FundingPayment } from '../libraries/FundingPayment.sol';\nimport { TickExtended } from '../libraries/TickExtended.sol';\n\nimport { IVToken } from '../interfaces/IVToken.sol';\n\nimport { UniswapV3PoolMock } from './mocks/UniswapV3PoolMock.sol';\n\ncontract TickExtendedTest {\n using FundingPayment for FundingPayment.Info;\n using TickExtended for mapping(int24 => TickExtended.Info);\n using TickExtended for IUniswapV3Pool;\n\n mapping(int24 => TickExtended.Info) public ticksExtended;\n\n FundingPayment.Info public fpGlobal;\n uint256 public sumFeeGlobalX128;\n\n int256 fundingRateOverrideX128 = type(int256).max;\n\n IUniswapV3Pool public vPool;\n\n constructor() {\n vPool = IUniswapV3Pool(address(new UniswapV3PoolMock()));\n }\n\n function setTick(int24 tickIndex, TickExtended.Info memory tick) external {\n ticksExtended[tickIndex] = tick;\n }\n\n function setFpGlobal(FundingPayment.Info calldata fpGlobal_) external {\n fpGlobal = fpGlobal_;\n }\n\n function setFeeGrowthOutsideX128(uint256 _extendedFeeGrowthOutsideX128) external {\n sumFeeGlobalX128 = _extendedFeeGrowthOutsideX128;\n }\n\n function getNetPositionInside(\n int24 tickLower,\n int24 tickUpper,\n int24 tickCurrent\n ) public view returns (int256 netPositionGrowthX128) {\n (netPositionGrowthX128, , ) = ticksExtended.getTickExtendedStateInside(\n tickLower,\n tickUpper,\n tickCurrent,\n fpGlobal,\n sumFeeGlobalX128\n );\n }\n\n function getFundingPaymentGrowthInside(\n int24 tickLower,\n int24 tickUpper,\n int24 tickCurrent\n ) public view returns (int256 fundingPaymentGrowth) {\n (, fundingPaymentGrowth, ) = ticksExtended.getTickExtendedStateInside(\n tickLower,\n tickUpper,\n tickCurrent,\n fpGlobal,\n sumFeeGlobalX128\n );\n }\n\n function getFeeGrowthInside(\n int24 tickLower,\n int24 tickUpper,\n int24 tickCurrent\n ) public view returns (uint256 extendedFeeGrowthInside) {\n (, , extendedFeeGrowthInside) = ticksExtended.getTickExtendedStateInside(\n tickLower,\n tickUpper,\n tickCurrent,\n fpGlobal,\n sumFeeGlobalX128\n );\n }\n\n function registerTrade(\n int256 vTokenAmount,\n uint256 liquidity,\n uint48 blockTimestamp,\n uint256 virtualPriceX128,\n int256 fundingRateX128\n ) public {\n fpGlobal.update(vTokenAmount, liquidity, blockTimestamp, fundingRateX128, virtualPriceX128);\n }\n\n function cross(int24 tickNext) external {\n ticksExtended.cross(tickNext, fpGlobal, sumFeeGlobalX128);\n }\n}\n" + }, + "contracts/test/mocks/UniswapV3PoolMock.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\ncontract UniswapV3PoolMock {\n struct Tick {\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 mapping(int24 => Tick) public ticks;\n\n function setTick(\n int24 tick,\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 ) external {\n ticks[tick].liquidityGross = liquidityGross;\n ticks[tick].liquidityNet = liquidityNet;\n ticks[tick].feeGrowthOutside0X128 = feeGrowthOutside0X128;\n ticks[tick].feeGrowthOutside1X128 = feeGrowthOutside1X128;\n ticks[tick].tickCumulativeOutside = tickCumulativeOutside;\n ticks[tick].secondsPerLiquidityOutsideX128 = secondsPerLiquidityOutsideX128;\n ticks[tick].secondsOutside = secondsOutside;\n ticks[tick].initialized = initialized;\n }\n\n uint256 public feeGrowthGlobal0X128;\n uint256 public feeGrowthGlobal1X128;\n\n function setFeeGrowth(uint256 _feeGrowthGlobal0X128, uint256 _feeGrowthGlobal1X128) external {\n feeGrowthGlobal0X128 = _feeGrowthGlobal0X128;\n feeGrowthGlobal1X128 = _feeGrowthGlobal1X128;\n }\n}\n" + }, + "contracts/test/SimulateSwapTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\nimport { IUniswapV3SwapCallback } from '@uniswap/v3-core-0.8-support/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\n\nimport { FundingPayment } from '../libraries/FundingPayment.sol';\nimport { SimulateSwap } from '../libraries/SimulateSwap.sol';\nimport { TickExtended } from '../libraries/TickExtended.sol';\n\nimport { IOracle } from '../interfaces/IOracle.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\n\ncontract SimulateSwapTest is IUniswapV3SwapCallback {\n using FullMath for uint256;\n using FundingPayment for FundingPayment.Info;\n using SafeERC20 for IERC20;\n using SimulateSwap for IUniswapV3Pool;\n using TickExtended for mapping(int24 => TickExtended.Info);\n\n IUniswapV3Pool vPool;\n\n struct SwapStep {\n SimulateSwap.State state;\n SimulateSwap.Step step;\n }\n SwapStep[] _steps;\n\n FundingPayment.Info public fpGlobal;\n uint256 public extendedFeeGrowthOutsideX128;\n mapping(int24 => TickExtended.Info) public ticksExtended;\n\n constructor(IUniswapV3Pool vPool_) {\n vPool = vPool_;\n }\n\n function clearSwapSteps() external {\n delete _steps;\n }\n\n function sqrtPrice() external view returns (uint160 sq) {\n (sq, , , , , , ) = vPool.slot0();\n }\n\n function simulateSwap1(\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96\n ) public returns (int256 amount0, int256 amount1) {\n (amount0, amount1, , ) = vPool.simulateSwap(zeroForOne, amountSpecified, sqrtPriceLimitX96, _onSwapStep);\n }\n\n function simulateSwap2(\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96\n )\n public\n returns (\n int256 amount0,\n int256 amount1,\n SimulateSwap.Cache memory cache,\n SwapStep[] memory steps\n )\n {\n (amount0, amount1, , cache) = vPool.simulateSwap(zeroForOne, amountSpecified, sqrtPriceLimitX96, _onSwapStep);\n steps = _steps;\n }\n\n function simulateSwap3(\n bool swapVTokenForVQuote,\n int256 amountSpecified,\n uint24 fee\n ) public returns (int256 vTokenIn, int256 vQuoteIn) {\n // case isNotional true\n // amountSpecified is positive\n SimulateSwap.Cache memory cache;\n cache.fee = fee;\n cache.tickSpacing = vPool.tickSpacing();\n (vTokenIn, vQuoteIn, ) = vPool.simulateSwap(\n swapVTokenForVQuote,\n amountSpecified,\n swapVTokenForVQuote ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1,\n cache,\n _onSwapStep\n );\n }\n\n function _onSwapStep(\n bool,\n SimulateSwap.Cache memory,\n SimulateSwap.State memory state,\n SimulateSwap.Step memory step\n ) internal {\n // for reading\n _steps.push(SwapStep({ state: state, step: step }));\n }\n\n function swap(\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96\n ) external returns (int256 amount0, int256 amount1) {\n return vPool.swap(msg.sender, zeroForOne, amountSpecified, sqrtPriceLimitX96, abi.encode(msg.sender));\n }\n\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == address(vPool));\n address receipient = abi.decode(data, (address));\n if (amount0Delta > 0) {\n IERC20(vPool.token0()).safeTransferFrom(receipient, address(vPool), uint256(amount0Delta));\n }\n if (amount1Delta > 0) {\n IERC20(vPool.token1()).safeTransferFrom(receipient, address(vPool), uint256(amount1Delta));\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "contracts/test/mocks/OracleMock.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { IOracle } from '../../interfaces/IOracle.sol';\n\nimport { PriceMath } from '../../libraries/PriceMath.sol';\n\ncontract OracleMock is IOracle {\n using PriceMath for uint256;\n using PriceMath for uint160;\n\n uint256 priceX128;\n\n constructor() {\n setPriceX128(1 << 128);\n }\n\n function getTwapPriceX128(uint32) external view returns (uint256) {\n return priceX128;\n }\n\n function getTwapSqrtPriceX96(uint32) external view returns (uint160 sqrtPriceX96) {\n sqrtPriceX96 = priceX128.toSqrtPriceX96();\n }\n\n function setSqrtPriceX96(uint160 _sqrtPriceX96) public {\n priceX128 = _sqrtPriceX96.toPriceX128();\n }\n\n function setPriceX128(uint256 _priceX128) public {\n priceX128 = _priceX128;\n }\n}\n" + }, + "contracts/test/PriceMathTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { PriceMath } from '../libraries/PriceMath.sol';\n\ncontract PriceMathTest {\n function toPriceX128(uint160 sqrtPriceX96) public pure returns (uint256 priceX128) {\n return PriceMath.toPriceX128(sqrtPriceX96);\n }\n\n function toSqrtPriceX96(uint256 priceX128) public pure returns (uint160 sqrtPriceX96) {\n return PriceMath.toSqrtPriceX96(priceX128);\n }\n}\n" + }, + "contracts/test/mocks/ArbSysMock.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { IOracle } from '../../interfaces/IOracle.sol';\n\nimport { PriceMath } from '../../libraries/PriceMath.sol';\n\ncontract ArbSysMock {\n using PriceMath for uint256;\n using PriceMath for uint160;\n\n uint256 public arbBlockNumber;\n\n constructor() {\n setArbBlockNumber(0);\n }\n\n function setArbBlockNumber(uint256 _arbBlockNumber) public {\n arbBlockNumber = _arbBlockNumber;\n }\n}\n" + }, + "contracts/protocol/RageTradeFactory.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.14;\n\nimport { IERC20Metadata } from '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport { ProxyAdmin } from '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol';\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\nimport { IUniswapV3Factory } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Factory.sol';\n\nimport { ClearingHouseDeployer } from './clearinghouse/ClearingHouseDeployer.sol';\nimport { InsuranceFundDeployer } from './insurancefund/InsuranceFundDeployer.sol';\nimport { VQuoteDeployer } from './tokens/VQuoteDeployer.sol';\nimport { VTokenDeployer } from './tokens/VTokenDeployer.sol';\nimport { VToken } from './tokens/VToken.sol';\nimport { VPoolWrapperDeployer } from './wrapper/VPoolWrapperDeployer.sol';\n\nimport { IClearingHouse } from '../interfaces/IClearingHouse.sol';\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IInsuranceFund } from '../interfaces/IInsuranceFund.sol';\nimport { IOracle } from '../interfaces/IOracle.sol';\nimport { IVQuote } from '../interfaces/IVQuote.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\n\nimport { AddressHelper } from '../libraries/AddressHelper.sol';\nimport { PriceMath } from '../libraries/PriceMath.sol';\n\nimport { ClearingHouseExtsload } from '../extsloads/ClearingHouseExtsload.sol';\nimport { SettlementTokenOracle } from '../oracles/SettlementTokenOracle.sol';\nimport { Governable } from '../utils/Governable.sol';\n\nimport { UNISWAP_V3_FACTORY_ADDRESS, UNISWAP_V3_DEFAULT_FEE_TIER } from '../utils/constants.sol';\n\ncontract RageTradeFactory is\n Governable,\n ClearingHouseDeployer,\n InsuranceFundDeployer,\n VQuoteDeployer,\n VPoolWrapperDeployer,\n VTokenDeployer\n{\n using AddressHelper for address;\n using ClearingHouseExtsload for IClearingHouse;\n using PriceMath for uint256;\n\n IVQuote public immutable vQuote;\n IClearingHouse public immutable clearingHouse;\n\n event PoolInitialized(IUniswapV3Pool vPool, IVToken vToken, IVPoolWrapper vPoolWrapper);\n\n /// @notice Sets up the protocol by deploying necessary core contracts\n /// @dev Need to deploy logic contracts for ClearingHouse, VPoolWrapper, InsuranceFund prior to this\n constructor(\n address clearingHouseLogicAddress,\n address _vPoolWrapperLogicAddress,\n address insuranceFundLogicAddress,\n IERC20Metadata settlementToken,\n IOracle settlementTokenOracle\n ) VPoolWrapperDeployer(_vPoolWrapperLogicAddress) {\n proxyAdmin = _deployProxyAdmin();\n proxyAdmin.transferOwnership(msg.sender);\n\n // deploys VQuote contract at an address which has most significant nibble as \"f\"\n vQuote = _deployVQuote(settlementToken.decimals());\n\n // deploys InsuranceFund proxy\n IInsuranceFund insuranceFund = _deployProxyForInsuranceFund(insuranceFundLogicAddress);\n\n // deploys a proxy for ClearingHouse, and initialize it as well\n clearingHouse = _deployProxyForClearingHouseAndInitialize(\n ClearingHouseDeployer.DeployClearingHouseParams(\n clearingHouseLogicAddress,\n settlementToken,\n settlementTokenOracle,\n insuranceFund,\n vQuote\n )\n );\n\n _initializeInsuranceFund(insuranceFund, settlementToken, clearingHouse);\n }\n\n struct InitializePoolParams {\n VTokenDeployer.DeployVTokenParams deployVTokenParams;\n IClearingHouseStructures.PoolSettings poolInitialSettings;\n uint24 liquidityFeePips;\n uint24 protocolFeePips;\n uint16 slotsToInitialize;\n }\n\n /// @notice Sets up a new Rage Trade Pool by deploying necessary contracts\n /// @dev An already deployed oracle contract address (implementing IOracle) is needed prior to using this\n /// @param initializePoolParams parameters for initializing the pool\n function initializePool(InitializePoolParams calldata initializePoolParams) external onlyGovernance {\n // as an argument to vtoken constructer and make wrapper variable as immutable.\n // this will save sload on all vtoken mints (swaps liqudity adds).\n // STEP 1: Deploy the virtual token ERC20, such that it will be token0\n IVToken vToken = _deployVToken(initializePoolParams.deployVTokenParams);\n\n // STEP 2: Deploy vPool (token0=vToken, token1=vQuote) on actual uniswap\n IUniswapV3Pool vPool = _createUniswapV3Pool(vToken);\n\n // STEP 3: Initialize the price on the vPool\n vPool.initialize(\n initializePoolParams\n .poolInitialSettings\n .oracle\n .getTwapPriceX128(initializePoolParams.poolInitialSettings.twapDuration)\n .toSqrtPriceX96()\n );\n\n vPool.increaseObservationCardinalityNext(initializePoolParams.slotsToInitialize);\n\n // STEP 4: Deploys a proxy for the wrapper contract for the vPool, and initialize it as well\n IVPoolWrapper vPoolWrapper = _deployProxyForVPoolWrapperAndInitialize(\n IVPoolWrapper.InitializeVPoolWrapperParams(\n address(clearingHouse),\n vToken,\n vQuote,\n vPool,\n initializePoolParams.liquidityFeePips,\n initializePoolParams.protocolFeePips\n )\n );\n\n // STEP 5: Authorize vPoolWrapper in vToken and vQuote, for minting/burning whenever needed\n vQuote.authorize(address(vPoolWrapper));\n vToken.setVPoolWrapper(address(vPoolWrapper));\n clearingHouse.registerPool(\n IClearingHouseStructures.Pool(vToken, vPool, vPoolWrapper, initializePoolParams.poolInitialSettings)\n );\n\n emit PoolInitialized(vPool, vToken, vPoolWrapper);\n }\n\n function _createUniswapV3Pool(IVToken vToken) internal returns (IUniswapV3Pool) {\n return\n IUniswapV3Pool(\n IUniswapV3Factory(UNISWAP_V3_FACTORY_ADDRESS).createPool(\n address(vQuote),\n address(vToken),\n UNISWAP_V3_DEFAULT_FEE_TIER\n )\n );\n }\n\n function _isIVTokenAddressGood(address addr) internal view virtual override returns (bool) {\n uint32 poolId = addr.truncate();\n return\n // Zero element is considered empty in Uint32L8Array.sol\n poolId != 0 &&\n // vToken should be token0 and vQuote should be token1 in UniswapV3Pool\n (uint160(addr) < uint160(address(vQuote))) &&\n // there should not be a collision in poolIds\n clearingHouse.isPoolIdAvailable(poolId);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Factory.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title The interface for the Uniswap V3 Factory\n/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees\ninterface IUniswapV3Factory {\n /// @notice Emitted when the owner of the factory is changed\n /// @param oldOwner The owner before the owner was changed\n /// @param newOwner The owner after the owner was changed\n event OwnerChanged(address indexed oldOwner, address indexed newOwner);\n\n /// @notice Emitted when a pool is created\n /// @param token0 The first token of the pool by address sort order\n /// @param token1 The second token of the pool by address sort order\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks\n /// @param pool The address of the created pool\n event PoolCreated(\n address indexed token0,\n address indexed token1,\n uint24 indexed fee,\n int24 tickSpacing,\n address pool\n );\n\n /// @notice Emitted when a new fee amount is enabled for pool creation via the factory\n /// @param fee The enabled fee, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee\n event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);\n\n /// @notice Returns the current owner of the factory\n /// @dev Can be changed by the current owner via setOwner\n /// @return The address of the factory owner\n function owner() external view returns (address);\n\n /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled\n /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context\n /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee\n /// @return The tick spacing\n function feeAmountTickSpacing(uint24 fee) external view returns (int24);\n\n /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist\n /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order\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 pool address\n function getPool(\n address tokenA,\n address tokenB,\n uint24 fee\n ) external view returns (address pool);\n\n /// @notice Creates a pool for the given two tokens and fee\n /// @param tokenA One of the two tokens in the desired pool\n /// @param tokenB The other of the two tokens in the desired pool\n /// @param fee The desired fee for the pool\n /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved\n /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments\n /// are invalid.\n /// @return pool The address of the newly created pool\n function createPool(\n address tokenA,\n address tokenB,\n uint24 fee\n ) external returns (address pool);\n\n /// @notice Updates the owner of the factory\n /// @dev Must be called by the current owner\n /// @param _owner The new owner of the factory\n function setOwner(address _owner) external;\n\n /// @notice Enables a fee amount with the given tickSpacing\n /// @dev Fee amounts may never be removed once enabled\n /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)\n /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount\n function enableFeeAmount(uint24 fee, int24 tickSpacing) external;\n}\n" + }, + "contracts/protocol/clearinghouse/ClearingHouseDeployer.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.14;\n\nimport { TransparentUpgradeableProxy } from '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol';\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { ProxyAdminDeployer } from '../../utils/ProxyAdminDeployer.sol';\n\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\nimport { IClearingHouseSystemActions } from '../../interfaces/clearinghouse/IClearingHouseSystemActions.sol';\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\nimport { IOracle } from '../../interfaces/IOracle.sol';\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\n\n/// @notice Manages deployment for ClearingHouseProxy\n/// @dev ClearingHouse proxy is deployed only once\nabstract contract ClearingHouseDeployer is ProxyAdminDeployer {\n struct DeployClearingHouseParams {\n address clearingHouseLogicAddress;\n IERC20 settlementToken;\n IOracle settlementTokenOracle;\n IInsuranceFund insuranceFund;\n IVQuote vQuote;\n }\n\n function _deployProxyForClearingHouseAndInitialize(DeployClearingHouseParams memory params)\n internal\n returns (IClearingHouse)\n {\n return\n IClearingHouse(\n address(\n new TransparentUpgradeableProxy(\n params.clearingHouseLogicAddress,\n address(proxyAdmin),\n abi.encodeCall(\n IClearingHouseSystemActions.initialize,\n (\n address(this), // RageTradeFactory\n msg.sender, // initialGovernance\n msg.sender, // initialTeamMultisig\n params.settlementToken,\n params.settlementTokenOracle,\n params.insuranceFund,\n params.vQuote\n )\n )\n )\n )\n );\n }\n}\n" + }, + "contracts/protocol/insurancefund/InsuranceFundDeployer.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.14;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport { TransparentUpgradeableProxy } from '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol';\n\nimport { ProxyAdminDeployer } from '../../utils/ProxyAdminDeployer.sol';\n\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\n\nabstract contract InsuranceFundDeployer is ProxyAdminDeployer {\n function _deployProxyForInsuranceFund(address insuranceFundLogicAddress) internal returns (IInsuranceFund) {\n return\n IInsuranceFund(\n address(new TransparentUpgradeableProxy(insuranceFundLogicAddress, address(proxyAdmin), hex''))\n );\n }\n\n function _initializeInsuranceFund(\n IInsuranceFund insuranceFund,\n IERC20 settlementToken,\n IClearingHouse clearingHouse\n ) internal {\n insuranceFund.initialize(\n settlementToken,\n address(clearingHouse),\n 'RageTrade iSettlementToken',\n 'iSettlementToken'\n );\n }\n}\n" + }, + "contracts/protocol/tokens/VQuoteDeployer.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.14;\n\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\n\nimport { GoodAddressDeployer } from '../../libraries/GoodAddressDeployer.sol';\n\nimport { VQuote } from '../tokens/VQuote.sol';\n\nabstract contract VQuoteDeployer {\n function _deployVQuote(uint8 rSettlementTokenDecimals) internal returns (IVQuote vQuote) {\n return\n IVQuote(\n GoodAddressDeployer.deploy(\n 0,\n abi.encodePacked(type(VQuote).creationCode, abi.encode(rSettlementTokenDecimals)),\n _isVQuoteAddressGood\n )\n );\n }\n\n // returns true if most significant hex char of address is \"f\"\n function _isVQuoteAddressGood(address addr) private pure returns (bool) {\n return (uint160(addr) >> 156) == 0xf;\n }\n}\n" + }, + "contracts/protocol/tokens/VTokenDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.8.14;\n\nimport { Create2 } from '@openzeppelin/contracts/utils/Create2.sol';\n\nimport { GoodAddressDeployer } from '../../libraries/GoodAddressDeployer.sol';\n\nimport { VToken, IVToken } from './VToken.sol';\n\nabstract contract VTokenDeployer {\n struct DeployVTokenParams {\n string vTokenName;\n string vTokenSymbol;\n uint8 cTokenDecimals;\n }\n\n /// @notice Deploys contract VToken at an address such that the last 4 bytes of contract address is unique\n /// @dev Use of CREATE2 is not to recompute address in future, but just to have unique last 4 bytes\n /// @param params: parameters used for construction, see above struct\n /// @return vToken : the deployed VToken contract\n function _deployVToken(DeployVTokenParams calldata params) internal returns (IVToken vToken) {\n bytes memory bytecode = abi.encodePacked(\n type(VToken).creationCode,\n abi.encode(params.vTokenName, params.vTokenSymbol, params.cTokenDecimals)\n );\n\n vToken = IVToken(GoodAddressDeployer.deploy(0, bytecode, _isIVTokenAddressGood));\n }\n\n /// @notice Checks if it is fine to deploy vToken at the provided address\n /// @dev This method is implemented in RageTradeFactory\n /// @param addr potential address of vToken\n /// @return true if last 4 bytes are non-zero,\n function _isIVTokenAddressGood(address addr) internal view virtual returns (bool);\n}\n" + }, + "contracts/protocol/tokens/VToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.8.14;\n\nimport { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport { Ownable } from '@openzeppelin/contracts/access/Ownable.sol';\n\nimport { IVToken } from '../../interfaces/IVToken.sol';\n\ncontract VToken is ERC20, IVToken, Ownable {\n address public vPoolWrapper;\n\n uint8 immutable _decimals;\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n\n constructor(\n string memory vTokenName,\n string memory vTokenSymbol,\n uint8 cTokenDecimals\n ) ERC20(vTokenName, vTokenSymbol) {\n _decimals = cTokenDecimals;\n }\n\n error Unauthorised();\n\n function setVPoolWrapper(address _vPoolWrapper) external onlyOwner {\n if (vPoolWrapper == address(0)) {\n vPoolWrapper = _vPoolWrapper;\n }\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256\n ) internal view override {\n // transfer cases:\n // - vPoolWrapper mints tokens at uniswap pool address\n // - uniswap v3 pool transfers tokens to vPoolWrapper\n // - vPoolWrapper burns all tokens it has, at its own address\n if (!(from == address(0) || to == address(0) || from == vPoolWrapper || to == vPoolWrapper)) {\n revert Unauthorised();\n }\n }\n\n function mint(address receiver, uint256 amount) external {\n if (msg.sender != vPoolWrapper) {\n revert Unauthorised();\n }\n _mint(receiver, amount);\n }\n\n function burn(uint256 amount) external {\n _burn(msg.sender, amount);\n }\n}\n" + }, + "contracts/protocol/wrapper/VPoolWrapperDeployer.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.14;\n\nimport { TransparentUpgradeableProxy } from '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol';\n\nimport { IVPoolWrapper } from '../../interfaces/IVPoolWrapper.sol';\n\nimport { Governable } from '../../utils/Governable.sol';\nimport { ClearingHouseDeployer } from '../clearinghouse/ClearingHouseDeployer.sol';\n\nabstract contract VPoolWrapperDeployer is Governable, ClearingHouseDeployer {\n address public vPoolWrapperLogicAddress;\n\n error IllegalAddress(address addr);\n\n constructor(address _vPoolWrapperLogicAddress) {\n vPoolWrapperLogicAddress = _vPoolWrapperLogicAddress;\n }\n\n /// @notice Admin method to set latest implementation logic for VPoolWrapper\n /// @param _vPoolWrapperLogicAddress: new logic address\n /// @dev When a new vPoolWrapperLogic is deployed, make sure that the initialize method is called.\n function setVPoolWrapperLogicAddress(address _vPoolWrapperLogicAddress) external onlyGovernance {\n if (_vPoolWrapperLogicAddress == address(0)) {\n revert IllegalAddress(address(0));\n }\n\n vPoolWrapperLogicAddress = _vPoolWrapperLogicAddress;\n }\n\n function _deployProxyForVPoolWrapperAndInitialize(IVPoolWrapper.InitializeVPoolWrapperParams memory params)\n internal\n returns (IVPoolWrapper vPoolWrapper)\n {\n return\n IVPoolWrapper(\n address(\n new TransparentUpgradeableProxy(\n address(vPoolWrapperLogicAddress),\n address(proxyAdmin),\n abi.encodeCall(IVPoolWrapper.initialize, (params))\n )\n )\n );\n }\n}\n" + }, + "contracts/oracles/SettlementTokenOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport { IOracle } from '../interfaces/IOracle.sol';\n\ncontract SettlementTokenOracle is IOracle {\n function getTwapPriceX128(uint32) external pure returns (uint256 priceX128) {\n priceX128 = 1 << 128;\n }\n}\n" + }, + "contracts/utils/Governable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\n\nimport { ContextUpgradeable } from '@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol';\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\n\nimport { IGovernable } from '../interfaces/IGovernable.sol';\n\n/// @title Governable module that exposes onlyGovernance and onlyGovernanceOrTeamMultisig modifiers\n/// @notice Copied and modified from @openzeppelin/contracts/access/Ownable.sol\nabstract contract Governable is IGovernable, Initializable, ContextUpgradeable {\n address private _governance;\n address private _teamMultisig;\n address private _governancePending;\n address private _teamMultisigPending;\n\n event GovernanceTransferred(address indexed previousGovernance, address indexed newGovernance);\n event TeamMultisigTransferred(address indexed previousTeamMultisig, address indexed newTeamMultisig);\n event GovernancePending(address indexed previousGovernancePending, address indexed newGovernancePending);\n event TeamMultisigPending(address indexed previousTeamMultisigPending, address indexed newTeamMultisigPending);\n\n error Unauthorised();\n error ZeroAddress();\n\n /// @notice Initializes the contract setting the deployer as the initial governance and team multisig.\n constructor() {\n __Governable_init();\n }\n\n /// @notice Useful to proxy contracts for initializing\n function __Governable_init() internal initializer {\n __Context_init();\n address msgSender = _msgSender();\n __Governable_init(msgSender, msgSender);\n }\n\n /// @notice Useful to proxy contracts for initializing with custom addresses\n /// @param initialGovernance the initial governance address\n /// @param initialTeamMultisig the initial teamMultisig address\n function __Governable_init(address initialGovernance, address initialTeamMultisig) internal initializer {\n _governance = initialGovernance;\n emit GovernanceTransferred(address(0), initialGovernance);\n\n _teamMultisig = initialTeamMultisig;\n emit TeamMultisigTransferred(address(0), initialTeamMultisig);\n }\n\n /// @notice Returns the address of the current governance.\n\n function governance() public view virtual returns (address) {\n return _governance;\n }\n\n /// @notice Returns the address of the current governance.\n function governancePending() public view virtual returns (address) {\n return _governancePending;\n }\n\n /// @notice Returns the address of the current team multisig.transferTeamMultisig\n function teamMultisig() public view virtual returns (address) {\n return _teamMultisig;\n }\n\n /// @notice Returns the address of the current team multisig.transferTeamMultisig\n function teamMultisigPending() public view virtual returns (address) {\n return _teamMultisigPending;\n }\n\n /// @notice Throws if called by any account other than the governance.\n modifier onlyGovernance() {\n if (governance() != _msgSender()) revert Unauthorised();\n _;\n }\n\n /// @notice Throws if called by any account other than the governance or team multisig.\n modifier onlyGovernanceOrTeamMultisig() {\n if (teamMultisig() != _msgSender() && governance() != _msgSender()) revert Unauthorised();\n _;\n }\n\n /// @notice Initiates governance transfer to a new account (`newGovernancePending`).\n /// @param newGovernancePending the new governance address\n function initiateGovernanceTransfer(address newGovernancePending) external virtual onlyGovernance {\n emit GovernancePending(_governancePending, newGovernancePending);\n _governancePending = newGovernancePending;\n }\n\n /// @notice Completes governance transfer, on being called by _governancePending.\n function acceptGovernanceTransfer() external virtual {\n if (_msgSender() != _governancePending) revert Unauthorised();\n\n emit GovernanceTransferred(_governance, _governancePending);\n _governance = _governancePending;\n _governancePending = address(0);\n }\n\n /// @notice Initiates teamMultisig transfer to a new account (`newTeamMultisigPending`).\n /// @param newTeamMultisigPending the new team multisig address\n function initiateTeamMultisigTransfer(address newTeamMultisigPending)\n external\n virtual\n onlyGovernanceOrTeamMultisig\n {\n emit TeamMultisigPending(_teamMultisigPending, newTeamMultisigPending);\n _teamMultisigPending = newTeamMultisigPending;\n }\n\n /// @notice Completes teamMultisig transfer, on being called by _teamMultisigPending.\n function acceptTeamMultisigTransfer() external virtual {\n if (_msgSender() != _teamMultisigPending) revert Unauthorised();\n\n emit TeamMultisigTransferred(_teamMultisig, _teamMultisigPending);\n _teamMultisig = _teamMultisigPending;\n _teamMultisigPending = address(0);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overriden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "contracts/utils/ProxyAdminDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { ProxyAdmin } from '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol';\n\nabstract contract ProxyAdminDeployer {\n ProxyAdmin public proxyAdmin;\n\n function _deployProxyAdmin() internal returns (ProxyAdmin) {\n return new ProxyAdmin();\n }\n}\n" + }, + "contracts/libraries/GoodAddressDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { Create2 } from '@openzeppelin/contracts/utils/Create2.sol';\n\n/// @title Deploys a new contract at a desirable address\nlibrary GoodAddressDeployer {\n /// @notice Deploys contract at an address such that the function isAddressGood(address) returns true\n /// @dev Use of CREATE2 is not to recompute address in future, but just to have the address good\n /// @param amount: constructor payable ETH amount\n /// @param bytecode: creation bytecode (should include constructor args)\n /// @param isAddressGood: boolean function that should return true for good addresses\n function deploy(\n uint256 amount,\n bytes memory bytecode,\n function(address) returns (bool) isAddressGood\n ) internal returns (address computed) {\n return deploy(amount, bytecode, isAddressGood, uint256(blockhash(block.number - 1)));\n }\n\n /// @notice Deploys contract at an address such that the function isAddressGood(address) returns true\n /// @dev Use of CREATE2 is not to recompute address in future, but just to have the address good\n /// @param amount: constructor payable ETH amount\n /// @param bytecode: creation bytecode (should include constructor args)\n /// @param isAddressGood: boolean function that should return true for good addresses\n /// @param salt: initial salt, should be pseudo-randomized so that there won't be more for loop iterations if\n /// state used in isAddressGood is updated after deployment\n function deploy(\n uint256 amount,\n bytes memory bytecode,\n function(address) returns (bool) isAddressGood,\n uint256 salt\n ) internal returns (address computed) {\n bytes32 byteCodeHash = keccak256(bytecode);\n\n while (true) {\n computed = Create2.computeAddress(bytes32(salt), byteCodeHash);\n\n if (isAddressGood(computed)) {\n // we found good address, so stop the for loop and proceed\n break;\n } else {\n // since address is not what we'd like, using a different salt\n unchecked {\n salt++;\n }\n }\n }\n\n address deployed = Create2.deploy(amount, bytes32(salt), bytecode);\n assert(computed == deployed);\n }\n}\n" + }, + "contracts/protocol/tokens/VQuote.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.14;\n\nimport { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport { Ownable } from '@openzeppelin/contracts/access/Ownable.sol';\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\nimport { IVPoolWrapper } from '../../interfaces/IVPoolWrapper.sol';\n\ncontract VQuote is IVQuote, ERC20('Rage Trade Virtual Quote Token', 'vQuote'), Ownable {\n mapping(address => bool) public isAuth;\n\n uint8 immutable _decimals;\n\n constructor(uint8 decimals_) {\n _decimals = decimals_;\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256\n ) internal view override {\n // transfer cases:\n // - vPoolWrapper mints tokens at uniswap pool address\n // - uniswap v3 pool transfers tokens to vPoolWrapper\n // - vPoolWrapper burns all tokens it has, at its own address\n if (!(from == address(0) || to == address(0) || isAuth[from] || isAuth[to])) {\n revert Unauthorised();\n }\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n\n function authorize(address vPoolWrapper) external onlyOwner {\n isAuth[vPoolWrapper] = true;\n }\n\n error Unauthorised();\n\n function mint(address account, uint256 amount) external {\n if (!isAuth[msg.sender]) {\n revert Unauthorised();\n }\n _mint(account, amount);\n }\n\n function burn(uint256 amount) external {\n _burn(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Create2.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(\n uint256 amount,\n bytes32 salt,\n bytes memory bytecode\n ) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(\n bytes32 salt,\n bytes32 bytecodeHash,\n address deployer\n ) internal pure returns (address) {\n bytes32 _data = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash));\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, _allowances[owner][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = _allowances[owner][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Spend `amount` form the allowance of `owner` toward `spender`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/test/Governable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { Governable } from '../utils/Governable.sol';\n\ncontract GovernableTest is Governable {}\n" + }, + "contracts/protocol/insurancefund/InsuranceFund.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.8.14;\n\nimport { ERC20Upgradeable } from '@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol';\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\n\ncontract InsuranceFund is IInsuranceFund, Initializable, ERC20Upgradeable {\n using SafeERC20 for IERC20;\n\n IERC20 public settlementToken;\n IClearingHouse public clearingHouse;\n\n error Unauthorised();\n\n /// @notice Initializer for Insurance Fund\n /// @param _settlementToken settlement token\n /// @param _clearingHouse address of clearing house (proxy) contract\n /// @param name \"Rage Trade iSettlementToken\"\n /// @param symbol \"iSettlementToken\"\n function initialize(\n IERC20 _settlementToken,\n address _clearingHouse,\n string calldata name,\n string calldata symbol\n ) external initializer {\n settlementToken = _settlementToken;\n clearingHouse = IClearingHouse(_clearingHouse);\n __ERC20_init(name, symbol);\n }\n\n function deposit(uint256 amount) external {\n uint256 totalBalance = settlementToken.balanceOf(address(this));\n uint256 totalShares = totalSupply();\n uint256 toMint;\n if (totalShares == 0 || totalBalance == 0) {\n toMint = amount;\n } else {\n toMint = (amount * totalShares) / totalBalance;\n }\n settlementToken.safeTransferFrom(msg.sender, address(this), amount);\n _mint(msg.sender, toMint);\n }\n\n function withdraw(uint256 shares) external {\n uint256 totalBalance = settlementToken.balanceOf(address(this));\n uint256 totalShares = totalSupply();\n uint256 toWithdraw = (shares * totalBalance) / totalShares;\n _burn(msg.sender, shares);\n settlementToken.safeTransfer(msg.sender, toWithdraw);\n }\n\n function claim(uint256 amount) external {\n if (address(clearingHouse) != msg.sender) revert Unauthorised();\n settlementToken.safeTransfer(msg.sender, amount);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, _allowances[owner][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = _allowances[owner][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Spend `amount` form the allowance of `owner` toward `spender`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n\n /**\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" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol';\n" + }, + "contracts/test/mocks/RealTokenMock1.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\n// if importing uniswap v3 libraries this might not work\npragma solidity ^0.8.9;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol';\n\ncontract RealTokenMockDecimals is ERC20PresetMinterPauser {\n uint8 immutable _decimals;\n\n constructor(uint8 decimalsToSet) ERC20PresetMinterPauser('WETH', 'WETH') {\n _decimals = decimalsToSet;\n }\n\n function decimals() public view override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../extensions/ERC20Burnable.sol\";\nimport \"../extensions/ERC20Pausable.sol\";\nimport \"../../../access/AccessControlEnumerable.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev {ERC20} token, including:\n *\n * - ability for holders to burn (destroy) their tokens\n * - a minter role that allows for token minting (creation)\n * - a pauser role that allows to stop all token transfers\n *\n * This contract uses {AccessControl} to lock permissioned functions using the\n * different roles - head to its documentation for details.\n *\n * The account that deploys the contract will be granted the minter and pauser\n * roles, as well as the default admin role, which will let it grant both minter\n * and pauser roles to other accounts.\n *\n * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._\n */\ncontract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /**\n * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the\n * account that deploys the contract.\n *\n * See {ERC20-constructor}.\n */\n constructor(string memory name, string memory symbol) ERC20(name, symbol) {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`.\n *\n * See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(address to, uint256 amount) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have minter role to mint\");\n _mint(to, amount);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to pause\");\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to unpause\");\n _unpause();\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20, ERC20Pausable) {\n super._beforeTokenTransfer(from, to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n */\nabstract contract ERC20Pausable is ERC20, Pausable {\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerable.sol\";\nimport \"./AccessControl.sol\";\nimport \"../utils/structs/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override {\n super._grantRole(role, account);\n _roleMembers[role].add(account);\n }\n\n /**\n * @dev Overload {_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override {\n super._revokeRole(role, account);\n _roleMembers[role].remove(account);\n }\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n return _values(set._inner);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "contracts/test/mocks/SettlementTokenMock.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { ERC20PresetMinterPauser } from '@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol';\n\ncontract SettlementTokenMock is ERC20PresetMinterPauser {\n constructor() ERC20PresetMinterPauser('USDC', 'USDC') {}\n\n function decimals() public pure override returns (uint8) {\n return 6;\n }\n}\n" + }, + "@openzeppelin/contracts/governance/TimelockController.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (governance/TimelockController.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../access/AccessControl.sol\";\n\n/**\n * @dev Contract module which acts as a timelocked controller. When set as the\n * owner of an `Ownable` smart contract, it enforces a timelock on all\n * `onlyOwner` maintenance operations. This gives time for users of the\n * controlled contract to exit before a potentially dangerous maintenance\n * operation is applied.\n *\n * By default, this contract is self administered, meaning administration tasks\n * have to go through the timelock process. The proposer (resp executor) role\n * is in charge of proposing (resp executing) operations. A common use case is\n * to position this {TimelockController} as the owner of a smart contract, with\n * a multisig or a DAO as the sole proposer.\n *\n * _Available since v3.3._\n */\ncontract TimelockController is AccessControl {\n bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\"TIMELOCK_ADMIN_ROLE\");\n bytes32 public constant PROPOSER_ROLE = keccak256(\"PROPOSER_ROLE\");\n bytes32 public constant EXECUTOR_ROLE = keccak256(\"EXECUTOR_ROLE\");\n uint256 internal constant _DONE_TIMESTAMP = uint256(1);\n\n mapping(bytes32 => uint256) private _timestamps;\n uint256 private _minDelay;\n\n /**\n * @dev Emitted when a call is scheduled as part of operation `id`.\n */\n event CallScheduled(\n bytes32 indexed id,\n uint256 indexed index,\n address target,\n uint256 value,\n bytes data,\n bytes32 predecessor,\n uint256 delay\n );\n\n /**\n * @dev Emitted when a call is performed as part of operation `id`.\n */\n event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);\n\n /**\n * @dev Emitted when operation `id` is cancelled.\n */\n event Cancelled(bytes32 indexed id);\n\n /**\n * @dev Emitted when the minimum delay for future operations is modified.\n */\n event MinDelayChange(uint256 oldDuration, uint256 newDuration);\n\n /**\n * @dev Initializes the contract with a given `minDelay`.\n */\n constructor(\n uint256 minDelay,\n address[] memory proposers,\n address[] memory executors\n ) {\n _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);\n _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);\n\n // deployer + self administration\n _setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());\n _setupRole(TIMELOCK_ADMIN_ROLE, address(this));\n\n // register proposers\n for (uint256 i = 0; i < proposers.length; ++i) {\n _setupRole(PROPOSER_ROLE, proposers[i]);\n }\n\n // register executors\n for (uint256 i = 0; i < executors.length; ++i) {\n _setupRole(EXECUTOR_ROLE, executors[i]);\n }\n\n _minDelay = minDelay;\n emit MinDelayChange(0, minDelay);\n }\n\n /**\n * @dev Modifier to make a function callable only by a certain role. In\n * addition to checking the sender's role, `address(0)` 's role is also\n * considered. Granting a role to `address(0)` is equivalent to enabling\n * this role for everyone.\n */\n modifier onlyRoleOrOpenRole(bytes32 role) {\n if (!hasRole(role, address(0))) {\n _checkRole(role, _msgSender());\n }\n _;\n }\n\n /**\n * @dev Contract might receive/hold ETH as part of the maintenance process.\n */\n receive() external payable {}\n\n /**\n * @dev Returns whether an id correspond to a registered operation. This\n * includes both Pending, Ready and Done operations.\n */\n function isOperation(bytes32 id) public view virtual returns (bool pending) {\n return getTimestamp(id) > 0;\n }\n\n /**\n * @dev Returns whether an operation is pending or not.\n */\n function isOperationPending(bytes32 id) public view virtual returns (bool pending) {\n return getTimestamp(id) > _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Returns whether an operation is ready or not.\n */\n function isOperationReady(bytes32 id) public view virtual returns (bool ready) {\n uint256 timestamp = getTimestamp(id);\n return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;\n }\n\n /**\n * @dev Returns whether an operation is done or not.\n */\n function isOperationDone(bytes32 id) public view virtual returns (bool done) {\n return getTimestamp(id) == _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Returns the timestamp at with an operation becomes ready (0 for\n * unset operations, 1 for done operations).\n */\n function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp) {\n return _timestamps[id];\n }\n\n /**\n * @dev Returns the minimum delay for an operation to become valid.\n *\n * This value can be changed by executing an operation that calls `updateDelay`.\n */\n function getMinDelay() public view virtual returns (uint256 duration) {\n return _minDelay;\n }\n\n /**\n * @dev Returns the identifier of an operation containing a single\n * transaction.\n */\n function hashOperation(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt\n ) public pure virtual returns (bytes32 hash) {\n return keccak256(abi.encode(target, value, data, predecessor, salt));\n }\n\n /**\n * @dev Returns the identifier of an operation containing a batch of\n * transactions.\n */\n function hashOperationBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt\n ) public pure virtual returns (bytes32 hash) {\n return keccak256(abi.encode(targets, values, datas, predecessor, salt));\n }\n\n /**\n * @dev Schedule an operation containing a single transaction.\n *\n * Emits a {CallScheduled} event.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function schedule(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual onlyRole(PROPOSER_ROLE) {\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\n _schedule(id, delay);\n emit CallScheduled(id, 0, target, value, data, predecessor, delay);\n }\n\n /**\n * @dev Schedule an operation containing a batch of transactions.\n *\n * Emits one {CallScheduled} event per transaction in the batch.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function scheduleBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual onlyRole(PROPOSER_ROLE) {\n require(targets.length == values.length, \"TimelockController: length mismatch\");\n require(targets.length == datas.length, \"TimelockController: length mismatch\");\n\n bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);\n _schedule(id, delay);\n for (uint256 i = 0; i < targets.length; ++i) {\n emit CallScheduled(id, i, targets[i], values[i], datas[i], predecessor, delay);\n }\n }\n\n /**\n * @dev Schedule an operation that is to becomes valid after a given delay.\n */\n function _schedule(bytes32 id, uint256 delay) private {\n require(!isOperation(id), \"TimelockController: operation already scheduled\");\n require(delay >= getMinDelay(), \"TimelockController: insufficient delay\");\n _timestamps[id] = block.timestamp + delay;\n }\n\n /**\n * @dev Cancel an operation.\n *\n * Requirements:\n *\n * - the caller must have the 'proposer' role.\n */\n function cancel(bytes32 id) public virtual onlyRole(PROPOSER_ROLE) {\n require(isOperationPending(id), \"TimelockController: operation cannot be cancelled\");\n delete _timestamps[id];\n\n emit Cancelled(id);\n }\n\n /**\n * @dev Execute an (ready) operation containing a single transaction.\n *\n * Emits a {CallExecuted} event.\n *\n * Requirements:\n *\n * - the caller must have the 'executor' role.\n */\n function execute(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\n bytes32 id = hashOperation(target, value, data, predecessor, salt);\n _beforeCall(id, predecessor);\n _call(id, 0, target, value, data);\n _afterCall(id);\n }\n\n /**\n * @dev Execute an (ready) operation containing a batch of transactions.\n *\n * Emits one {CallExecuted} event per transaction in the batch.\n *\n * Requirements:\n *\n * - the caller must have the 'executor' role.\n */\n function executeBatch(\n address[] calldata targets,\n uint256[] calldata values,\n bytes[] calldata datas,\n bytes32 predecessor,\n bytes32 salt\n ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {\n require(targets.length == values.length, \"TimelockController: length mismatch\");\n require(targets.length == datas.length, \"TimelockController: length mismatch\");\n\n bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);\n _beforeCall(id, predecessor);\n for (uint256 i = 0; i < targets.length; ++i) {\n _call(id, i, targets[i], values[i], datas[i]);\n }\n _afterCall(id);\n }\n\n /**\n * @dev Checks before execution of an operation's calls.\n */\n function _beforeCall(bytes32 id, bytes32 predecessor) private view {\n require(isOperationReady(id), \"TimelockController: operation is not ready\");\n require(predecessor == bytes32(0) || isOperationDone(predecessor), \"TimelockController: missing dependency\");\n }\n\n /**\n * @dev Checks after execution of an operation's calls.\n */\n function _afterCall(bytes32 id) private {\n require(isOperationReady(id), \"TimelockController: operation is not ready\");\n _timestamps[id] = _DONE_TIMESTAMP;\n }\n\n /**\n * @dev Execute an operation's call.\n *\n * Emits a {CallExecuted} event.\n */\n function _call(\n bytes32 id,\n uint256 index,\n address target,\n uint256 value,\n bytes calldata data\n ) private {\n (bool success, ) = target.call{value: value}(data);\n require(success, \"TimelockController: underlying transaction reverted\");\n\n emit CallExecuted(id, index, target, value, data);\n }\n\n /**\n * @dev Changes the minimum timelock duration for future operations.\n *\n * Emits a {MinDelayChange} event.\n *\n * Requirements:\n *\n * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing\n * an operation where the timelock is the target and the data is the ABI-encoded call to this function.\n */\n function updateDelay(uint256 newDelay) external virtual {\n require(msg.sender == address(this), \"TimelockController: caller must be timelock\");\n emit MinDelayChange(_minDelay, newDelay);\n _minDelay = newDelay;\n }\n}\n" + }, + "contracts/utils/TimelockControllerWithMinDelayOverride.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { TimelockController } from '@openzeppelin/contracts/governance/TimelockController.sol';\n\n/// @title Timelock controller with a minimum delay override for certain functions\ncontract TimelockControllerWithMinDelayOverride is TimelockController {\n uint256 private _minDelayOverridePlusOne;\n mapping(bytes32 => uint256) private _minDelayOverridePlusOneMapping;\n\n event MinDelayOverrideSet(address target, bytes4 selector, uint256 newMinDelay);\n event MinDelayOverrideUnset(address target, bytes4 selector);\n\n constructor(\n uint256 minDelay,\n address[] memory proposers,\n address[] memory executors\n ) TimelockController(minDelay, proposers, executors) {}\n\n function setMinDelayOverride(\n address target,\n bytes4 selector,\n uint256 minDelayOverride\n ) public {\n require(msg.sender == address(this), 'TimelockController: caller must be timelock');\n _minDelayOverridePlusOneMapping[_getKey(target, selector)] = minDelayOverride + 1;\n emit MinDelayOverrideSet(target, selector, minDelayOverride);\n }\n\n function unsetMinDelayOverride(address target, bytes4 selector) public {\n require(msg.sender == address(this), 'TimelockController: caller must be timelock');\n delete _minDelayOverridePlusOneMapping[_getKey(target, selector)];\n emit MinDelayOverrideUnset(target, selector);\n }\n\n function getMinDelayOverride(address target, bytes4 selector) external view returns (uint256 minDelayOverride) {\n uint256 minDelayOverridePlusOne = _minDelayOverridePlusOneMapping[_getKey(target, selector)];\n require(minDelayOverridePlusOne > 0, 'TimelockController: minDelayOverride not set');\n return minDelayOverridePlusOne - 1;\n }\n\n function schedule(\n address target,\n uint256 value,\n bytes calldata data,\n bytes32 predecessor,\n bytes32 salt,\n uint256 delay\n ) public virtual override onlyRole(PROPOSER_ROLE) {\n if (data.length >= 4) {\n uint256 minDelayOverridePlusOne = _minDelayOverridePlusOneMapping[_getKey(target, _getSelector(data))];\n if (minDelayOverridePlusOne != 0) {\n _minDelayOverridePlusOne = minDelayOverridePlusOne; // SSTORE\n }\n }\n super.schedule(target, value, data, predecessor, salt, delay);\n delete _minDelayOverridePlusOne;\n }\n\n function getMinDelay() public view virtual override returns (uint256 duration) {\n uint256 minDelayOverridePlusOne = _minDelayOverridePlusOne;\n return minDelayOverridePlusOne == 0 ? super.getMinDelay() : minDelayOverridePlusOne - 1;\n }\n\n function _getSelector(bytes calldata data) internal pure returns (bytes4 selector) {\n assert(data.length >= 4);\n assembly {\n // clear first memory word\n mstore(0, 0)\n // copy calldata to memory scratch space\n calldatacopy(0, data.offset, 4)\n // load memory to stack\n selector := mload(0)\n }\n }\n\n function _getKey(address target, bytes4 selector) internal pure returns (bytes32 c) {\n assembly {\n // store target in the last 20 bytes and selector in the 4 bytes before\n c := xor(target, selector)\n }\n }\n}\n" + }, + "contracts/test/TimelockControllerWithMinDelayOverrideTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { TimelockControllerWithMinDelayOverride } from '../utils/TimelockControllerWithMinDelayOverride.sol';\n\ncontract TimelockControllerWithMinDelayOverrideTest is TimelockControllerWithMinDelayOverride {\n constructor(\n uint256 minDelay,\n address[] memory proposers,\n address[] memory executors\n ) TimelockControllerWithMinDelayOverride(minDelay, proposers, executors) {}\n\n // replicate similar calldata like in schedule function\n function getSelector(\n address,\n uint256,\n bytes calldata data,\n bytes32,\n bytes32,\n uint256\n ) public pure returns (bytes4 selector) {\n bytes32 m1_before;\n bytes32 m2_before;\n bytes32 m3_before;\n assembly {\n m1_before := mload(0x20)\n m2_before := mload(0x40)\n m3_before := mload(0x60)\n }\n\n selector = _getSelector(data);\n\n bytes32 m1_after;\n bytes32 m2_after;\n bytes32 m3_after;\n assembly {\n m1_after := mload(0x20)\n m2_after := mload(0x40)\n m3_after := mload(0x60)\n }\n\n // ensuring that _getSelector didn't screw up memory past m0\n assert(m1_before == m1_after);\n assert(m2_before == m2_after);\n assert(m3_before == m3_after);\n }\n\n function getKey(address target, bytes4 selector) public pure returns (bytes32 c) {\n return _getKey(target, selector);\n }\n}\n" + }, + "contracts/test/mocks/RealTokenMock.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\n// if importing uniswap v3 libraries this might not work\npragma solidity ^0.8.9;\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol';\n\ncontract RealTokenMock is ERC20PresetMinterPauser {\n constructor() ERC20PresetMinterPauser('WETH', 'WETH') {}\n}\n" + }, + "contracts/test/CollateralDepositSetTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Uint32L8ArrayLib } from '../libraries/Uint32L8Array.sol';\nimport { VPoolWrapperMock } from './mocks/VPoolWrapperMock.sol';\n\nimport { AddressHelper } from '../libraries/AddressHelper.sol';\nimport { CollateralDeposit } from '../libraries/CollateralDeposit.sol';\n\nimport { IVToken } from '../interfaces/IVToken.sol';\nimport { IOracle } from '../interfaces/IOracle.sol';\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\n\nimport { AccountProtocolInfoMock } from './mocks/AccountProtocolInfoMock.sol';\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\ncontract CollateralDepositSetTest is AccountProtocolInfoMock {\n using CollateralDeposit for CollateralDeposit.Set;\n using AddressHelper for address;\n using AddressHelper for IERC20;\n using Uint32L8ArrayLib for uint32[8];\n\n CollateralDeposit.Set depositTokenSet;\n\n VPoolWrapperMock public wrapper;\n\n constructor(address _settlementToken) {\n wrapper = new VPoolWrapperMock();\n protocol.settlementToken = IERC20(_settlementToken);\n }\n\n function initVToken(address vToken) external {\n protocol.pools[vToken.truncate()].vToken = IVToken(vToken);\n }\n\n function init(\n IERC20 cToken,\n IOracle oracle,\n uint32 twapDuration\n ) external {\n IClearingHouseStructures.Collateral memory collateral = IClearingHouseStructures.Collateral(\n cToken,\n IClearingHouseStructures.CollateralSettings(oracle, twapDuration, true)\n );\n protocol.collaterals[collateral.token.truncate()] = collateral;\n }\n\n function cleanDeposits() external {\n for (uint256 i = 0; i < depositTokenSet.active.length; i++) {\n uint32 collateralId = depositTokenSet.active[i];\n if (collateralId == 0) break;\n\n depositTokenSet.decreaseBalance(collateralId, depositTokenSet.deposits[collateralId]);\n }\n }\n\n function increaseBalance(address realTokenAddress, uint256 amount) external {\n depositTokenSet.increaseBalance(realTokenAddress.truncate(), amount);\n }\n\n function decreaseBalance(address realTokenAddress, uint256 amount) external {\n depositTokenSet.decreaseBalance(realTokenAddress.truncate(), amount);\n }\n\n function getAllDepositAccountMarketValue() external view returns (int256 depositValue) {\n return depositTokenSet.marketValue(protocol);\n }\n\n function getBalance(address realTokenAddress) external view returns (uint256 balance) {\n return depositTokenSet.deposits[realTokenAddress.truncate()];\n }\n}\n" + }, + "contracts/test/ClearingHouseTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport { Account } from '../libraries/Account.sol';\nimport { CollateralDeposit } from '../libraries/CollateralDeposit.sol';\nimport { LiquidityPositionSet } from '../libraries/LiquidityPositionSet.sol';\nimport { VTokenPositionSet } from '../libraries/VTokenPositionSet.sol';\nimport { LiquidityPosition } from '../libraries/LiquidityPosition.sol';\nimport { VTokenPosition } from '../libraries/VTokenPosition.sol';\nimport { SignedFullMath } from '../libraries/SignedFullMath.sol';\nimport { AddressHelper } from '../libraries/AddressHelper.sol';\nimport { Protocol } from '../libraries/Protocol.sol';\n\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\nimport { IVQuote } from '../interfaces/IVQuote.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\n\nimport { ClearingHouse } from '../protocol/clearinghouse/ClearingHouse.sol';\n\ncontract ClearingHouseTest is ClearingHouse {\n using AddressHelper for address;\n using AddressHelper for IVToken;\n using SignedFullMath for int256;\n\n using Account for Account.Info;\n using CollateralDeposit for CollateralDeposit.Set;\n using LiquidityPositionSet for LiquidityPosition.Set;\n using LiquidityPosition for LiquidityPosition.Info;\n using Protocol for Protocol.Info;\n using VTokenPositionSet for VTokenPosition.Set;\n using VTokenPosition for VTokenPosition.Info;\n\n function isPoolIdAvailable(uint32 poolId) external view returns (bool) {\n return protocol.pools[poolId].vToken.isZero();\n }\n\n function getPoolInfo(uint32 poolId) public view returns (Pool memory) {\n return protocol.pools[poolId];\n }\n\n function getProtocolInfo()\n public\n view\n returns (\n IERC20 settlementToken,\n IVQuote vQuote,\n LiquidationParams memory liquidationParams,\n uint256 minRequiredMargin,\n uint256 removeLimitOrderFee,\n uint256 minimumOrderNotional\n )\n {\n settlementToken = protocol.settlementToken;\n vQuote = protocol.vQuote;\n liquidationParams = protocol.liquidationParams;\n minRequiredMargin = protocol.minRequiredMargin;\n removeLimitOrderFee = protocol.removeLimitOrderFee;\n minimumOrderNotional = protocol.minimumOrderNotional;\n }\n\n function getCollateralInfo(uint32 collateralId) public view returns (Collateral memory) {\n return protocol.collaterals[collateralId];\n }\n\n function getAccountInfo(uint256 accountId)\n public\n view\n returns (\n address owner,\n int256 vQuoteBalance,\n CollateralDepositView[] memory collateralDeposits,\n VTokenPositionView[] memory tokenPositions\n )\n {\n return accounts[accountId].getInfo(protocol);\n }\n\n function getTruncatedTokenAddress(IVToken vToken) external pure returns (uint32) {\n return vToken.truncate();\n }\n\n function cleanPositions(uint256 accountId) external {\n VTokenPosition.Set storage set = accounts[accountId].tokenPositions;\n VTokenPosition.Info storage tokenPosition;\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\n\n set.vQuoteBalance = 0;\n\n for (uint8 i = 0; i < set.active.length; i++) {\n uint32 poolId = set.active[i];\n if (poolId == 0) break;\n tokenPosition = set.positions[poolId];\n balanceAdjustments = IClearingHouseStructures.BalanceAdjustments(\n 0,\n -tokenPosition.balance,\n -tokenPosition.netTraderPosition\n );\n set.update(accountId, balanceAdjustments, poolId, protocol);\n }\n }\n\n function cleanDeposits(uint256 accountId) external {\n accounts[accountId].tokenPositions.liquidateLiquidityPositions(accountId, protocol);\n\n CollateralDeposit.Set storage set = accounts[accountId].collateralDeposits;\n uint256 deposit;\n\n for (uint8 i = 0; i < set.active.length; i++) {\n uint32 collateralId = set.active[i];\n if (collateralId == 0) break;\n deposit = set.deposits[collateralId];\n set.decreaseBalance(collateralId, deposit);\n }\n }\n\n function getTokenAddressInVTokens(IVToken vToken) external view returns (IVToken vTokenInIVTokenes) {\n return protocol.pools[vToken.truncate()].vToken;\n }\n\n function getAccountOwner(uint256 accountId) external view returns (address owner) {\n return accounts[accountId].owner;\n }\n\n // function getAccountNumInTokenPositionSet(uint256 accountId) external view returns (uint256 accountIdInTokenSet) {\n // return accounts[accountId].tokenPositions.accountId;\n // }\n\n function getAccountDepositBalance(uint256 accountId, IVToken vToken) external view returns (uint256 balance) {\n balance = accounts[accountId].collateralDeposits.deposits[vToken.truncate()];\n }\n\n function getAccountOpenTokenPosition(uint256 accountId, IVToken vToken)\n external\n view\n returns (int256 balance, int256 netTraderPosition)\n {\n VTokenPosition.Info storage vTokenPosition = accounts[accountId].tokenPositions.positions[vToken.truncate()];\n balance = vTokenPosition.balance;\n netTraderPosition = vTokenPosition.netTraderPosition;\n }\n\n function getAccountQuoteBalance(uint256 accountId) external view returns (int256 balance) {\n return accounts[accountId].tokenPositions.vQuoteBalance;\n }\n\n function getAccountLiquidityPositionNum(uint256 accountId, address vToken) external view returns (uint8 num) {\n LiquidityPosition.Set storage liquidityPositionSet = accounts[accountId]\n .tokenPositions\n .positions[vToken.truncate()]\n .liquidityPositions;\n\n for (num = 0; num < liquidityPositionSet.active.length; num++) {\n if (liquidityPositionSet.active[num] == 0) break;\n }\n }\n\n function getAccountTokenPositionFunding(uint256 accountId, IVToken vToken)\n external\n view\n returns (int256 fundingPayment)\n {\n VTokenPosition.Info storage vTokenPosition = accounts[accountId].tokenPositions.positions[vToken.truncate()];\n\n IVPoolWrapper wrapper = protocol.vPoolWrapper(vToken.truncate());\n\n fundingPayment = vTokenPosition.unrealizedFundingPayment(wrapper);\n }\n\n function getAccountLiquidityPositionFundingAndFee(\n uint256 accountId,\n address vToken,\n uint8 num\n ) external view returns (int256 fundingPayment, uint256 unrealizedLiquidityFee) {\n LiquidityPosition.Set storage liquidityPositionSet = accounts[accountId]\n .tokenPositions\n .positions[vToken.truncate()]\n .liquidityPositions;\n LiquidityPosition.Info storage liquidityPosition = liquidityPositionSet.positions[\n liquidityPositionSet.active[num]\n ];\n\n IVPoolWrapper.WrapperValuesInside memory wrapperValuesInside = protocol\n .vPoolWrapper(vToken.truncate())\n .getExtrapolatedValuesInside(liquidityPosition.tickLower, liquidityPosition.tickUpper);\n\n fundingPayment = liquidityPosition.unrealizedFundingPayment(\n wrapperValuesInside.sumAX128,\n wrapperValuesInside.sumFpInsideX128\n );\n\n unrealizedLiquidityFee = liquidityPosition.unrealizedFees(wrapperValuesInside.sumFeeInsideX128);\n }\n\n function getAccountLiquidityPositionDetails(\n uint256 accountId,\n address vToken,\n uint8 num\n )\n external\n view\n returns (\n int24 tickLower,\n int24 tickUpper,\n IClearingHouseEnums.LimitOrderType limitOrderType,\n uint128 liquidity,\n int256 sumALastX128,\n int256 sumBInsideLastX128,\n int256 sumFpInsideLastX128,\n uint256 sumFeeInsideLastX128\n )\n {\n LiquidityPosition.Set storage liquidityPositionSet = accounts[accountId]\n .tokenPositions\n .positions[vToken.truncate()]\n .liquidityPositions;\n LiquidityPosition.Info storage liquidityPosition = liquidityPositionSet.positions[\n liquidityPositionSet.active[num]\n ];\n\n return (\n liquidityPosition.tickLower,\n liquidityPosition.tickUpper,\n liquidityPosition.limitOrderType,\n liquidityPosition.liquidity,\n liquidityPosition.sumALastX128,\n liquidityPosition.sumBInsideLastX128,\n liquidityPosition.sumFpInsideLastX128,\n liquidityPosition.sumFeeInsideLastX128\n );\n }\n\n function getAccountValueAndRequiredMargin(uint256 accountId, bool isInitialMargin)\n external\n view\n returns (int256 accountMarketValue, int256 requiredMargin)\n {\n return accounts[accountId].getAccountValueAndRequiredMargin(isInitialMargin, protocol);\n }\n}\n" + }, + "contracts/protocol/clearinghouse/ClearingHouse.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.14;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport { PausableUpgradeable } from '@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol';\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\n\nimport { Account } from '../../libraries/Account.sol';\nimport { AddressHelper } from '../../libraries/AddressHelper.sol';\nimport { BatchedLoop } from '../../libraries/BatchedLoop.sol';\nimport { Protocol } from '../../libraries/Protocol.sol';\nimport { SignedMath } from '../../libraries/SignedMath.sol';\n\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\nimport { IVPoolWrapper } from '../../interfaces/IVPoolWrapper.sol';\nimport { IOracle } from '../../interfaces/IOracle.sol';\nimport { IVQuote } from '../../interfaces/IVQuote.sol';\nimport { IVToken } from '../../interfaces/IVToken.sol';\n\nimport { IClearingHouseActions } from '../../interfaces/clearinghouse/IClearingHouseActions.sol';\nimport { IClearingHouseStructures } from '../../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IClearingHouseEnums } from '../../interfaces/clearinghouse/IClearingHouseEnums.sol';\nimport { IClearingHouseOwnerActions } from '../../interfaces/clearinghouse/IClearingHouseOwnerActions.sol';\nimport { IClearingHouseSystemActions } from '../../interfaces/clearinghouse/IClearingHouseSystemActions.sol';\n\nimport { Governable } from '../../utils/Governable.sol';\nimport { Multicall } from '../../utils/Multicall.sol';\nimport { ClearingHouseView } from './ClearingHouseView.sol';\n\ncontract ClearingHouse is\n IClearingHouse,\n Multicall,\n ClearingHouseView, // contains storage\n Initializable, // contains storage\n PausableUpgradeable, // contains storage\n Governable // contains storage\n{\n using AddressHelper for address;\n using AddressHelper for IERC20;\n using AddressHelper for IVToken;\n using SafeERC20 for IERC20;\n using SignedMath for int256;\n using SafeCast for uint256;\n using SafeCast for int256;\n\n using Account for Account.Info;\n using BatchedLoop for BatchedLoop.Info;\n using Protocol for Protocol.Info;\n\n uint16 constant PERC_100_BPS = 10000; // 100% in basis points\n uint16 constant PERC_10_1E5 = 10000; // 10% in base 1e5\n\n modifier onlyRageTradeFactory() {\n if (rageTradeFactoryAddress != msg.sender) revert NotRageTradeFactory();\n _;\n }\n\n /**\n SYSTEM FUNCTIONS\n */\n\n function initialize(\n address _rageTradeFactoryAddress,\n address initialGovernance,\n address initialTeamMultisig,\n IERC20 _defaultCollateralToken,\n IOracle _defaultCollateralTokenOracle,\n IInsuranceFund _insuranceFund,\n IVQuote _vQuote\n ) external initializer {\n rageTradeFactoryAddress = _rageTradeFactoryAddress;\n protocol.settlementToken = _defaultCollateralToken;\n insuranceFund = _insuranceFund;\n\n protocol.vQuote = _vQuote;\n\n _updateCollateralSettings(\n _defaultCollateralToken,\n CollateralSettings({ oracle: _defaultCollateralTokenOracle, twapDuration: 60, isAllowedForDeposit: true })\n );\n\n __Governable_init(initialGovernance, initialTeamMultisig);\n __Pausable_init_unchained();\n }\n\n function registerPool(Pool calldata poolInfo) external onlyRageTradeFactory {\n uint32 poolId = poolInfo.vToken.truncate();\n\n // pool will not be registered twice by the rage trade factory\n assert(protocol.pools[poolId].vToken.isZero());\n\n protocol.pools[poolId] = poolInfo;\n protocol.poolIds.push(poolId);\n\n emit PoolSettingsUpdated(poolId, poolInfo.settings);\n }\n\n /**\n WITHDRAWAL FUNCTION\n */\n function withdrawUSDCToTeamMultisig() external onlyGovernanceOrTeamMultisig {\n protocol.settlementToken.safeTransfer(teamMultisig(), protocol.settlementToken.balanceOf(address(this)));\n }\n\n /**\n ADMIN FUNCTIONS\n */\n\n function updateCollateralSettings(IERC20 cToken, CollateralSettings memory collateralSettings)\n external\n onlyGovernance\n {\n if ((address(collateralSettings.oracle)).isZero()) revert InvalidSetting(0x10);\n if (collateralSettings.twapDuration > 1 days) revert InvalidSetting(0x11);\n _updateCollateralSettings(cToken, collateralSettings);\n }\n\n function updatePoolSettings(uint32 poolId, PoolSettings calldata newSettings) external onlyGovernance {\n protocol.pools[poolId].settings = newSettings;\n if ((address(newSettings.oracle)).isZero()) revert InvalidSetting(0x20);\n if (newSettings.twapDuration < 5 minutes || newSettings.twapDuration > 1 days) revert InvalidSetting(0x21);\n if (newSettings.initialMarginRatioBps > PERC_100_BPS) revert InvalidSetting(0x22);\n if (newSettings.maintainanceMarginRatioBps > PERC_100_BPS) revert InvalidSetting(0x23);\n if (newSettings.maxVirtualPriceDeviationRatioBps > (PERC_100_BPS * 2) / 10) revert InvalidSetting(0x24);\n\n emit PoolSettingsUpdated(poolId, newSettings);\n }\n\n function updateProtocolSettings(\n LiquidationParams calldata _liquidationParams,\n uint256 _removeLimitOrderFee,\n uint256 _minimumOrderNotional,\n uint256 _minRequiredMargin\n ) external onlyGovernance {\n if (_liquidationParams.rangeLiquidationFeeFraction > PERC_10_1E5) revert InvalidSetting(0x30);\n if (_liquidationParams.tokenLiquidationFeeFraction > PERC_10_1E5) revert InvalidSetting(0x31);\n if (_liquidationParams.closeFactorMMThresholdBps > PERC_100_BPS) revert InvalidSetting(0x32);\n if (_liquidationParams.partialLiquidationCloseFactorBps > PERC_100_BPS) revert InvalidSetting(0x33);\n if (_liquidationParams.insuranceFundFeeShareBps > PERC_100_BPS) revert InvalidSetting(0x34);\n if (_liquidationParams.liquidationSlippageSqrtToleranceBps > PERC_100_BPS / 10) revert InvalidSetting(0x35);\n if (_liquidationParams.maxRangeLiquidationFees > 1000e6) revert InvalidSetting(0x36);\n if (_liquidationParams.minNotionalLiquidatable > 1000e6) revert InvalidSetting(0x37);\n if (_removeLimitOrderFee > 1000e6) revert InvalidSetting(0x38);\n if (_minimumOrderNotional > 1000e6) revert InvalidSetting(0x39);\n if (_minRequiredMargin > 1000e6) revert InvalidSetting(0x3A);\n\n protocol.liquidationParams = _liquidationParams;\n protocol.removeLimitOrderFee = _removeLimitOrderFee;\n protocol.minimumOrderNotional = _minimumOrderNotional;\n protocol.minRequiredMargin = _minRequiredMargin;\n emit ProtocolSettingsUpdated(\n _liquidationParams,\n _removeLimitOrderFee,\n _minimumOrderNotional,\n _minRequiredMargin\n );\n }\n\n function pause(uint256 numberOfPoolsToUpdateInThisTx) external onlyGovernanceOrTeamMultisig whenNotPaused {\n if (unpauseLoop.isInProgress()) revert CannotPauseIfUnpauseInProgress();\n\n bool completed = pauseLoop.iterate({\n startAt: 0,\n endBefore: protocol.poolIds.length,\n batchSize: numberOfPoolsToUpdateInThisTx,\n execute: _forEachPoolOnPause\n });\n\n if (completed) _pause();\n }\n\n function unpause(uint256 numberOfPoolsToUpdateInThisTx) external onlyGovernanceOrTeamMultisig whenPaused {\n if (pauseLoop.isInProgress()) revert CannotUnpauseIfPauseInProgress();\n\n bool completed = unpauseLoop.iterate({\n startAt: 0,\n endBefore: protocol.poolIds.length,\n batchSize: numberOfPoolsToUpdateInThisTx,\n execute: _forEachPoolOnUnpause\n });\n\n if (completed) _unpause();\n }\n\n /// @inheritdoc IClearingHouseOwnerActions\n function withdrawProtocolFee(uint256 numberOfPoolsToUpdateInThisTx) external {\n withdrawProtocolFeeLoop.iterate({\n startAt: 0,\n endBefore: protocol.poolIds.length,\n batchSize: numberOfPoolsToUpdateInThisTx,\n execute: _forEachPoolOnWithdrawProtocolFee\n });\n }\n\n /**\n USER FUNCTIONS\n */\n\n /// @inheritdoc IClearingHouseActions\n function createAccount() public whenNotPaused returns (uint256 newAccountId) {\n newAccountId = numAccounts;\n numAccounts = newAccountId + 1; // SSTORE\n\n Account.Info storage newAccount = accounts[newAccountId];\n newAccount.owner = msg.sender;\n newAccount.id = uint96(newAccountId);\n\n emit AccountCreated(msg.sender, newAccountId);\n }\n\n /// @inheritdoc IClearingHouseActions\n function updateMargin(\n uint256 accountId,\n uint32 collateralId,\n int256 amount\n ) public whenNotPaused {\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\n _updateAccountPoolPrices(account);\n _updateMargin(account, collateralId, amount, amount < 0);\n }\n\n /// @inheritdoc IClearingHouseActions\n function createAccountAndAddMargin(uint32 collateralId, uint256 amount) external returns (uint256 newAccountId) {\n newAccountId = createAccount();\n updateMargin(newAccountId, collateralId, int256(amount));\n }\n\n /// @inheritdoc IClearingHouseActions\n function updateProfit(uint256 accountId, int256 amount) external whenNotPaused {\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\n _updateAccountPoolPrices(account);\n _updateProfit(account, amount, true);\n }\n\n /// @inheritdoc IClearingHouseActions\n function settleProfit(uint256 accountId) external whenNotPaused {\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\n _updateAccountPoolPrices(account);\n account.settleProfit(protocol);\n }\n\n /// @inheritdoc IClearingHouseActions\n function swapToken(\n uint256 accountId,\n uint32 poolId,\n SwapParams memory swapParams\n ) external whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\n _updateAccountPoolPrices(account);\n return _swapToken(account, poolId, swapParams, true);\n }\n\n /// @inheritdoc IClearingHouseActions\n function updateRangeOrder(\n uint256 accountId,\n uint32 poolId,\n LiquidityChangeParams calldata liquidityChangeParams\n ) external whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n Account.Info storage account = _getAccountAndCheckOwner(accountId);\n _updateAccountPoolPrices(account);\n return _updateRangeOrder(account, poolId, liquidityChangeParams, true);\n }\n\n /// @inheritdoc IClearingHouseActions\n function removeLimitOrder(\n uint256 accountId,\n uint32 poolId,\n int24 tickLower,\n int24 tickUpper\n ) external {\n _updateAccountPoolPrices(accounts[accountId]);\n _removeLimitOrder(accountId, poolId, tickLower, tickUpper);\n }\n\n /// @inheritdoc IClearingHouseActions\n function liquidateLiquidityPositions(uint256 accountId) external {\n _updateAccountPoolPrices(accounts[accountId]);\n _liquidateLiquidityPositions(accountId);\n }\n\n /// @inheritdoc IClearingHouseActions\n function liquidateTokenPosition(uint256 targetAccountId, uint32 poolId) external returns (int256 keeperFee) {\n _updateAccountPoolPrices(accounts[targetAccountId]);\n return _liquidateTokenPosition(targetAccountId, poolId);\n }\n\n /**\n MULTICALL\n */\n\n function multicallWithSingleMarginCheck(uint256 accountId, MulticallOperation[] calldata operations)\n external\n returns (bytes[] memory results)\n {\n results = new bytes[](operations.length);\n\n Account.Info storage account = accounts[accountId];\n _updateAccountPoolPrices(account);\n\n bool checkOwner = false;\n bool checkProfit = false;\n bool checkMargin = false;\n\n for (uint256 i; i < operations.length; i++) {\n if (operations[i].operationType == MulticallOperationType.UPDATE_MARGIN) {\n // ADD_MARGIN\n (uint32 collateralId, int256 amount) = abi.decode(operations[i].data, (uint32, int256));\n checkOwner = true;\n checkMargin = checkMargin || amount < 0;\n _updateMargin(account, collateralId, amount, false);\n } else if (operations[i].operationType == MulticallOperationType.UPDATE_PROFIT) {\n // UPDATE_PROFIT\n int256 amount = abi.decode(operations[i].data, (int256));\n _updateProfit(account, amount, false);\n checkOwner = true;\n if (amount < 0) {\n checkProfit = true;\n checkMargin = true;\n }\n } else if (operations[i].operationType == MulticallOperationType.SWAP_TOKEN) {\n // SWAP_TOKEN\n (uint32 poolId, SwapParams memory sp) = abi.decode(operations[i].data, (uint32, SwapParams));\n (int256 vTokenAmountOut, int256 vQuoteAmountOut) = _swapToken(account, poolId, sp, false);\n results[i] = abi.encode(vTokenAmountOut, vQuoteAmountOut);\n checkOwner = true;\n checkMargin = true;\n } else if (operations[i].operationType == MulticallOperationType.UPDATE_RANGE_ORDER) {\n // UPDATE_RANGE_ORDER\n (uint32 poolId, LiquidityChangeParams memory lcp) = abi.decode(\n operations[i].data,\n (uint32, LiquidityChangeParams)\n );\n (int256 vTokenAmountOut, int256 vQuoteAmountOut) = _updateRangeOrder(account, poolId, lcp, false);\n results[i] = abi.encode(vTokenAmountOut, vQuoteAmountOut);\n checkOwner = true;\n checkMargin = true;\n } else if (operations[i].operationType == MulticallOperationType.REMOVE_LIMIT_ORDER) {\n // REMOVE_LIMIT_ORDER\n (uint32 poolId, int24 tickLower, int24 tickUpper) = abi.decode(\n operations[i].data,\n (uint32, int24, int24)\n );\n _removeLimitOrder(accountId, poolId, tickLower, tickUpper);\n } else if (operations[i].operationType == MulticallOperationType.LIQUIDATE_LIQUIDITY_POSITIONS) {\n // LIQUIDATE_LIQUIDITY_POSITIONS\n uint32 accountToLiquidate = abi.decode(operations[i].data, (uint32));\n _liquidateLiquidityPositions(accountToLiquidate);\n } else if (operations[i].operationType == MulticallOperationType.LIQUIDATE_TOKEN_POSITION) {\n // LIQUIDATE_TOKEN_POSITION\n (uint32 accountToLiquidate, uint32 poolId) = abi.decode(operations[i].data, (uint32, uint32));\n results[i] = abi.encode(_liquidateTokenPosition(accountToLiquidate, poolId));\n } else {\n revert InvalidMulticallOperationType(operations[i].operationType);\n }\n }\n\n // after all the operations are done, check the margin requirements\n if (checkOwner) _getAccountAndCheckOwner(accountId);\n if (checkProfit) account.checkIfProfitAvailable(protocol);\n if (checkMargin) account.checkIfMarginAvailable(true, protocol);\n\n return results;\n }\n\n /**\n INTERNAL HELPERS\n */\n\n function _updateAccountPoolPrices(Account.Info storage account) internal {\n account.updateAccountPoolPrices(protocol);\n }\n\n function _updateMargin(\n Account.Info storage account,\n uint32 collateralId,\n int256 amount,\n bool checkMargin\n ) internal whenNotPaused {\n Collateral storage collateral = _checkCollateralIdAndGetInfo({\n collateralId: collateralId,\n isWithdraw: amount < 0\n });\n\n // delegate call to account library to perform state update and emit events\n account.updateMargin(collateralId, amount, protocol, checkMargin);\n\n // transfer settlement tokens between clearing house and account owner\n if (amount > 0) {\n collateral.token.safeTransferFrom(msg.sender, address(this), uint256(amount));\n } else if (amount < 0) {\n collateral.token.safeTransfer(msg.sender, uint256(-amount));\n }\n }\n\n function _updateProfit(\n Account.Info storage account,\n int256 amount,\n bool checkMargin\n ) internal whenNotPaused {\n if (amount == 0) revert ZeroAmount();\n\n account.updateProfit(amount, protocol, checkMargin);\n if (amount > 0) {\n protocol.settlementToken.safeTransferFrom(msg.sender, address(this), uint256(amount));\n } else {\n protocol.settlementToken.safeTransfer(msg.sender, uint256(-amount));\n }\n }\n\n function _updateRangeOrder(\n Account.Info storage account,\n uint32 poolId,\n LiquidityChangeParams memory liquidityChangeParams,\n bool checkMargin\n ) internal whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n _checkPoolId(poolId);\n\n if (liquidityChangeParams.sqrtPriceCurrent != 0) {\n _checkSlippage(poolId, liquidityChangeParams.sqrtPriceCurrent, liquidityChangeParams.slippageToleranceBps);\n }\n\n uint256 notionalValueAbs;\n (vTokenAmountOut, vQuoteAmountOut, notionalValueAbs) = account.liquidityChange(\n poolId,\n liquidityChangeParams,\n protocol,\n checkMargin\n );\n\n if (notionalValueAbs < protocol.minimumOrderNotional) revert LowNotionalValue(notionalValueAbs);\n }\n\n function _swapToken(\n Account.Info storage account,\n uint32 poolId,\n SwapParams memory swapParams,\n bool checkMargin\n ) internal whenNotPaused returns (int256 vTokenAmountOut, int256 vQuoteAmountOut) {\n _checkPoolId(poolId);\n\n (vTokenAmountOut, vQuoteAmountOut) = account.swapToken(poolId, swapParams, protocol, checkMargin);\n\n uint256 vQuoteAmountOutAbs = uint256(vQuoteAmountOut.abs());\n if (vQuoteAmountOutAbs < protocol.minimumOrderNotional) revert LowNotionalValue(vQuoteAmountOutAbs);\n\n if (swapParams.sqrtPriceLimit != 0 && !swapParams.isPartialAllowed) {\n if (\n !((swapParams.isNotional && vQuoteAmountOut.abs() == swapParams.amount.abs()) ||\n (!swapParams.isNotional && vTokenAmountOut.abs() == swapParams.amount.abs()))\n ) revert SlippageBeyondTolerance();\n }\n }\n\n function _liquidateLiquidityPositions(uint256 accountId) internal whenNotPaused returns (int256) {\n Account.Info storage account = accounts[accountId];\n\n (int256 keeperFee, int256 insuranceFundFee, int256 accountMarketValue) = account.liquidateLiquidityPositions(\n protocol\n );\n\n int256 accountFee = keeperFee + insuranceFundFee;\n\n if (keeperFee <= 0) revert KeeperFeeNotPositive(keeperFee);\n protocol.settlementToken.safeTransfer(msg.sender, uint256(keeperFee));\n _transferInsuranceFundFee(insuranceFundFee);\n\n emit Account.LiquidityPositionsLiquidated(\n accountId,\n msg.sender,\n accountFee,\n keeperFee,\n insuranceFundFee,\n accountMarketValue\n );\n\n return keeperFee;\n }\n\n function _liquidateTokenPosition(uint256 accountId, uint32 poolId)\n internal\n whenNotPaused\n returns (int256 keeperFee)\n {\n Account.Info storage account = accounts[accountId];\n\n _checkPoolId(poolId);\n int256 insuranceFundFee;\n (keeperFee, insuranceFundFee) = account.liquidateTokenPosition(poolId, protocol);\n if (keeperFee <= 0) revert KeeperFeeNotPositive(keeperFee);\n protocol.settlementToken.safeTransfer(msg.sender, uint256(keeperFee));\n _transferInsuranceFundFee(insuranceFundFee);\n }\n\n function _removeLimitOrder(\n uint256 accountId,\n uint32 poolId,\n int24 tickLower,\n int24 tickUpper\n ) internal whenNotPaused returns (uint256 keeperFee) {\n Account.Info storage account = accounts[accountId];\n\n _checkPoolId(poolId);\n keeperFee = protocol.removeLimitOrderFee;\n\n account.removeLimitOrder(poolId, tickLower, tickUpper, keeperFee, protocol);\n\n protocol.settlementToken.safeTransfer(msg.sender, keeperFee);\n }\n\n function _transferInsuranceFundFee(int256 insuranceFundFee) internal {\n if (insuranceFundFee > 0) {\n protocol.settlementToken.safeTransfer(address(insuranceFund), uint256(insuranceFundFee));\n } else {\n insuranceFund.claim(uint256(-insuranceFundFee));\n }\n }\n\n function _updateCollateralSettings(IERC20 collateralToken, CollateralSettings memory collateralSettings) internal {\n uint32 collateralId = collateralToken.truncate();\n\n // doesn't allow zero address as a collateral token\n if (collateralToken.isZero()) revert InvalidCollateralAddress(address(0));\n\n // doesn't allow owner to change the cToken address when updating settings, once it's truncated previously\n if (\n !protocol.collaterals[collateralId].token.isZero() &&\n !protocol.collaterals[collateralId].token.eq(collateralToken)\n ) {\n revert IncorrectCollateralAddress(collateralToken, protocol.collaterals[collateralId].token);\n }\n\n protocol.collaterals[collateralId] = Collateral(collateralToken, collateralSettings);\n\n emit CollateralSettingsUpdated(collateralToken, collateralSettings);\n }\n\n /**\n INTERNAL VIEW METHODS\n */\n\n function _getAccountAndCheckOwner(uint256 accountId) internal view returns (Account.Info storage account) {\n account = accounts[accountId];\n if (msg.sender != account.owner) revert AccessDenied(msg.sender);\n }\n\n function _checkCollateralIdAndGetInfo(uint32 collateralId, bool isWithdraw)\n internal\n view\n returns (Collateral storage collateral)\n {\n collateral = protocol.collaterals[collateralId];\n if (collateral.token.isZero()) revert CollateralDoesNotExist(collateralId);\n // do not check if it is a withdraw operation, so that users can withdraw even if collateral is banned\n if (!isWithdraw && !collateral.settings.isAllowedForDeposit) revert CollateralNotAllowedForUse(collateralId);\n }\n\n function _checkPoolId(uint32 poolId) internal view {\n Pool storage pool = protocol.pools[poolId];\n if (pool.vToken.isZero()) revert PoolDoesNotExist(poolId);\n if (!pool.settings.isAllowedForTrade) revert PoolNotAllowedForTrade(poolId);\n }\n\n function _checkSlippage(\n uint32 poolId,\n uint160 sqrtPriceToCheck,\n uint16 slippageToleranceBps\n ) internal view {\n uint160 sqrtPriceCurrent = protocol.getVirtualCurrentSqrtPriceX96(poolId);\n uint160 diff = sqrtPriceCurrent > sqrtPriceToCheck\n ? sqrtPriceCurrent - sqrtPriceToCheck\n : sqrtPriceToCheck - sqrtPriceCurrent;\n if (diff > (slippageToleranceBps * sqrtPriceToCheck) / 1e4) {\n revert SlippageBeyondTolerance();\n }\n }\n\n /**\n PRIVATE METHODS\n */\n\n function _forEachPoolOnPause(uint256 index) private {\n uint32 poolId = protocol.poolIds[index];\n // account for the funding payment upto this moment before pausing\n protocol.pools[poolId].vPoolWrapper.updateGlobalFundingState({ useZeroFundingRate: false });\n }\n\n function _forEachPoolOnUnpause(uint256 index) private {\n uint32 poolId = protocol.poolIds[index];\n // record the funding payment as zero for the entire duration for which clearing house was paused.\n protocol.pools[poolId].vPoolWrapper.updateGlobalFundingState({ useZeroFundingRate: true });\n }\n\n function _forEachPoolOnWithdrawProtocolFee(uint256 index) private {\n uint32 poolId = protocol.poolIds[index];\n uint256 feeCollected = protocol.pools[poolId].vPoolWrapper.collectAccruedProtocolFee();\n // if any protocol fee was collected then transfer to multisig\n if (feeCollected != 0) {\n protocol.settlementToken.safeTransfer(teamMultisig(), feeCollected);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/libraries/BatchedLoop.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { Math } from '@openzeppelin/contracts/utils/math/Math.sol';\n\n/// @title Batched Loop Library\n/// @notice Aids to perform a lengthy loop in seperate txs\nlibrary BatchedLoop {\n uint256 constant NULL = 0;\n\n struct Info {\n uint256 progress; // of array element to resume the progress from\n }\n\n /// @notice Resumes the loop from where it left of previously\n /// @param loop: the loop object to resume (this is storage ref and val is mutated)\n /// @param startAt: the index to start from\n /// @param endBefore: the index to end at\n /// @param batchSize: number of iterations to perform in this batch\n /// @param execute: the function to execute for each iteration\n /// @dev translates to: for(uint i = startAt; i < endBefore; i++) { execute(i); }\n function iterate(\n BatchedLoop.Info storage loop,\n uint256 startAt,\n uint256 endBefore,\n uint256 batchSize,\n function(uint256) execute\n ) internal returns (bool completed) {\n // resume the loop from the stored progress else use startAt\n uint256 from = loop.progress;\n if (from == NULL) from = startAt;\n\n // use endBefore if batchSize is zero, else calculate end index\n uint256 to = batchSize == NULL ? endBefore : Math.min(from + batchSize, endBefore);\n\n // executes upto (to - 1)\n while (from < to) {\n execute(from);\n from++;\n }\n\n if (completed = (to == endBefore)) {\n // if loop was completed then reset the progress\n loop.progress = NULL;\n } else {\n // store the progress if partial execution of the loop\n loop.progress = to;\n }\n }\n\n /// @notice Checks if the loop is in progress\n /// @param loop: the loop object\n /// @return true if the loop is in progress else false\n function isInProgress(BatchedLoop.Info storage loop) internal view returns (bool) {\n return loop.progress != NULL;\n }\n}\n" + }, + "contracts/utils/Multicall.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity >=0.7.6;\npragma abicoder v2;\n\nimport { IMulticall } from '@uniswap/v3-periphery/contracts/interfaces/IMulticall.sol';\n\n/// @title Multicall\n/// @notice Enables calling multiple methods in a single call to the contract\nabstract contract Multicall is IMulticall {\n /// @inheritdoc IMulticall\n function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) {\n results = new bytes[](data.length);\n for (uint256 i = 0; i < data.length; i++) {\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n\n if (!success) {\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\n if (result.length < 68) revert();\n assembly {\n result := add(result, 0x04)\n }\n revert(abi.decode(result, (string)));\n }\n\n results[i] = result;\n }\n }\n}\n" + }, + "contracts/protocol/clearinghouse/ClearingHouseView.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.14;\n\nimport { IClearingHouse } from '../../interfaces/IClearingHouse.sol';\nimport { IClearingHouseView } from '../../interfaces/clearinghouse/IClearingHouseView.sol';\n\nimport { Account } from '../../libraries/Account.sol';\nimport { Protocol } from '../../libraries/Protocol.sol';\n\nimport { ClearingHouseStorage } from './ClearingHouseStorage.sol';\n\nimport { Extsload } from '../../utils/Extsload.sol';\n\nabstract contract ClearingHouseView is IClearingHouse, ClearingHouseStorage, Extsload {\n using Account for Account.Info;\n using Protocol for Protocol.Info;\n\n /// @inheritdoc IClearingHouseView\n function getAccountMarketValueAndRequiredMargin(uint256 accountId, bool isInitialMargin)\n public\n view\n returns (int256 marketValue, int256 requiredMargin)\n {\n (marketValue, requiredMargin) = accounts[accountId].getAccountValueAndRequiredMargin(isInitialMargin, protocol);\n }\n\n /// @inheritdoc IClearingHouseView\n function getAccountNetProfit(uint256 accountId) public view returns (int256 accountNetProfit) {\n accountNetProfit = accounts[accountId].getAccountPositionProfits(protocol);\n }\n\n /// @inheritdoc IClearingHouseView\n function getAccountNetTokenPosition(uint256 accountId, uint32 poolId) public view returns (int256 netPosition) {\n return accounts[accountId].getNetPosition(poolId, protocol);\n }\n\n /// @inheritdoc IClearingHouseView\n function getRealTwapPriceX128(uint32 poolId) public view returns (uint256 realPriceX128) {\n realPriceX128 = protocol.getCachedRealTwapPriceX128(poolId);\n }\n\n /// @inheritdoc IClearingHouseView\n function getVirtualTwapPriceX128(uint32 poolId) public view returns (uint256 virtualPriceX128) {\n virtualPriceX128 = protocol.getCachedVirtualTwapPriceX128(poolId);\n }\n}\n" + }, + "@uniswap/v3-periphery/contracts/interfaces/IMulticall.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\n/// @title Multicall interface\n/// @notice Enables calling multiple methods in a single call to the contract\ninterface IMulticall {\n /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed\n /// @dev The `msg.value` should not be trusted for any method callable from multicall.\n /// @param data The encoded function data for each of the calls to make to this contract\n /// @return results The results from each of the calls passed in via data\n function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);\n}\n" + }, + "contracts/protocol/clearinghouse/ClearingHouseStorage.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.8.14;\n\nimport { Account } from '../../libraries/Account.sol';\nimport { BatchedLoop } from '../../libraries/BatchedLoop.sol';\nimport { Protocol } from '../../libraries/Protocol.sol';\n\nimport { IInsuranceFund } from '../../interfaces/IInsuranceFund.sol';\nimport { IOracle } from '../../interfaces/IOracle.sol';\n\nabstract contract ClearingHouseStorage {\n // rest slots reserved for any states from inheritance in future\n uint256[100] private _emptySlots1;\n\n // at slot # 100\n Protocol.Info internal protocol;\n\n uint256 public numAccounts;\n mapping(uint256 => Account.Info) accounts;\n\n address public rageTradeFactoryAddress;\n IInsuranceFund public insuranceFund;\n\n // progress index, used for performing for loop\n // over an unbounded array in multiple txs\n BatchedLoop.Info internal pauseLoop;\n BatchedLoop.Info internal unpauseLoop;\n BatchedLoop.Info internal withdrawProtocolFeeLoop;\n\n // reserved for adding slots in future\n uint256[100] private _emptySlots2;\n}\n" + }, + "contracts/test/mocks/ClearingHouseDummy.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { ClearingHouse } from '../../protocol/clearinghouse/ClearingHouse.sol';\n\ncontract ClearingHouseDummy is ClearingHouse {\n // just to test upgradibility\n function newMethodAdded() public pure returns (uint256) {\n return 1234567890;\n }\n}\n" + }, + "contracts/test/ExtsloadTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Extsload } from '../utils/Extsload.sol';\n\ncontract ExtsloadTest is Extsload {\n constructor() {\n assembly {\n sstore(3, 9)\n sstore(4, 16)\n sstore(5, 25)\n }\n }\n}\n" + }, + "contracts/test/AccountTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Account } from '../libraries/Account.sol';\nimport { AddressHelper } from '../libraries/AddressHelper.sol';\nimport { CollateralDeposit } from '../libraries/CollateralDeposit.sol';\nimport { LiquidityPositionSet } from '../libraries/LiquidityPositionSet.sol';\nimport { Protocol } from '../libraries/Protocol.sol';\nimport { VPoolWrapperMock } from './mocks/VPoolWrapperMock.sol';\nimport { VTokenPosition } from '../libraries/VTokenPosition.sol';\nimport { VTokenPositionSet } from '../libraries/VTokenPositionSet.sol';\nimport { LiquidityPosition } from '../libraries/LiquidityPosition.sol';\n\nimport { IClearingHouseEnums } from '../interfaces/clearinghouse/IClearingHouseEnums.sol';\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IVQuote } from '../interfaces/IVQuote.sol';\nimport { IOracle } from '../interfaces/IOracle.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\ncontract AccountTest {\n using AddressHelper for address;\n using AddressHelper for IERC20;\n using AddressHelper for IVToken;\n\n using Account for Account.Info;\n using VTokenPosition for VTokenPosition.Info;\n using VTokenPositionSet for VTokenPosition.Set;\n using LiquidityPositionSet for LiquidityPosition.Set;\n using CollateralDeposit for CollateralDeposit.Set;\n\n mapping(uint256 => Account.Info) accounts;\n Protocol.Info public protocol;\n uint256 public fixFee;\n\n uint256 public numAccounts;\n\n constructor() {}\n\n function setAccountStorage(\n IClearingHouseStructures.LiquidationParams calldata liquidationParams,\n uint256 minRequiredMargin,\n uint256 removeLimitOrderFee,\n uint256 minimumOrderNotional,\n uint256 fixFee_,\n address settlementToken\n ) external {\n protocol.liquidationParams = liquidationParams;\n protocol.minRequiredMargin = minRequiredMargin;\n protocol.removeLimitOrderFee = removeLimitOrderFee;\n protocol.minimumOrderNotional = minimumOrderNotional;\n protocol.settlementToken = IERC20(settlementToken);\n fixFee = fixFee_;\n }\n\n function registerPool(IClearingHouseStructures.Pool calldata poolInfo) external {\n uint32 poolId = poolInfo.vToken.truncate();\n\n // pool will not be registered twice by the rage trade factory\n assert(protocol.pools[poolId].vToken.isZero());\n\n protocol.pools[poolId] = poolInfo;\n }\n\n function setVQuoteAddress(IVQuote _vQuote) external {\n protocol.vQuote = _vQuote;\n }\n\n function createAccount() external {\n Account.Info storage newAccount = accounts[numAccounts];\n newAccount.owner = msg.sender;\n // newAccount.tokenPositions.accountId = numAccounts;\n numAccounts++;\n }\n\n function cleanPositions(uint256 accountId) external {\n accounts[accountId].tokenPositions.liquidateLiquidityPositions(accountId, protocol);\n VTokenPosition.Set storage set = accounts[accountId].tokenPositions;\n VTokenPosition.Info storage tokenPosition;\n IClearingHouseStructures.BalanceAdjustments memory balanceAdjustments;\n\n set.vQuoteBalance = 0;\n\n for (uint8 i = 0; i < set.active.length; i++) {\n uint32 poolId = set.active[i];\n if (poolId == 0) break;\n tokenPosition = set.positions[poolId];\n balanceAdjustments = IClearingHouseStructures.BalanceAdjustments(\n 0,\n -tokenPosition.balance,\n -tokenPosition.netTraderPosition\n );\n set.update(accountId, balanceAdjustments, poolId, protocol);\n }\n }\n\n function cleanDeposits(uint256 accountId) external {\n accounts[accountId].tokenPositions.liquidateLiquidityPositions(accountId, protocol);\n CollateralDeposit.Set storage set = accounts[accountId].collateralDeposits;\n uint256 deposit;\n\n for (uint8 i = 0; i < set.active.length; i++) {\n uint32 collateralId = set.active[i];\n if (collateralId == 0) break;\n deposit = set.deposits[collateralId];\n set.decreaseBalance(collateralId, deposit);\n }\n }\n\n function initToken(address vToken) external {\n protocol.pools[vToken.truncate()].vToken = IVToken(vToken);\n }\n\n function initCollateral(\n IERC20 cToken,\n IOracle oracle,\n uint32 twapDuration\n ) external {\n IClearingHouseStructures.Collateral memory collateral = IClearingHouseStructures.Collateral(\n cToken,\n IClearingHouseStructures.CollateralSettings(oracle, twapDuration, true)\n );\n protocol.collaterals[collateral.token.truncate()] = collateral;\n }\n\n function addMargin(\n uint256 accountId,\n address realTokenAddress,\n uint256 amount\n ) external {\n accounts[accountId].updateMargin(realTokenAddress.truncate(), int256(amount), protocol, false);\n }\n\n function removeMargin(\n uint256 accountId,\n address realTokenAddress,\n uint256 amount\n ) external {\n accounts[accountId].updateMargin(realTokenAddress.truncate(), -int256(amount), protocol, true);\n }\n\n function updateProfit(uint256 accountId, int256 amount) external {\n accounts[accountId].updateProfit(amount, protocol, true);\n }\n\n function swapTokenAmount(\n uint256 accountId,\n address vToken,\n int256 amount\n ) external {\n accounts[accountId].swapToken(\n vToken.truncate(),\n IClearingHouseStructures.SwapParams(amount, 0, false, false, false),\n protocol,\n true\n );\n }\n\n function swapTokenNotional(\n uint256 accountId,\n address vToken,\n int256 amount\n ) external {\n accounts[accountId].swapToken(\n vToken.truncate(),\n IClearingHouseStructures.SwapParams(amount, 0, true, false, false),\n protocol,\n true\n );\n }\n\n function liquidityChange(\n uint256 accountId,\n address vToken,\n IClearingHouseStructures.LiquidityChangeParams memory liquidityChangeParams\n ) external {\n accounts[accountId].liquidityChange(vToken.truncate(), liquidityChangeParams, protocol, true);\n }\n\n function liquidateLiquidityPositions(uint256 accountId)\n external\n returns (\n int256 keeperFee,\n int256 insuranceFundFee,\n int256 accountMarketValue\n )\n {\n return accounts[accountId].liquidateLiquidityPositions(protocol);\n }\n\n function liquidateTokenPosition(uint256 accountId, address vToken) external {\n accounts[accountId].liquidateTokenPosition(vToken.truncate(), protocol);\n }\n\n function removeLimitOrder(\n uint256 accountId,\n address vToken,\n int24 tickLower,\n int24 tickUpper,\n uint256 removeLimitOrderFee\n ) external {\n accounts[accountId].removeLimitOrder(vToken.truncate(), tickLower, tickUpper, removeLimitOrderFee, protocol);\n }\n\n function getAccountDepositBalance(uint256 accountId, address vToken) external view returns (uint256) {\n return accounts[accountId].collateralDeposits.deposits[vToken.truncate()];\n }\n\n function getAccountTokenDetails(uint256 accountId, address vToken)\n external\n view\n returns (\n int256 balance,\n int256 netTraderPosition,\n int256 sumALast\n )\n {\n VTokenPosition.Info storage vTokenPosition = accounts[accountId].tokenPositions.positions[vToken.truncate()];\n return (vTokenPosition.balance, vTokenPosition.netTraderPosition, vTokenPosition.sumALastX128);\n }\n\n function getAccountQuoteBalance(uint256 accountId) external view returns (int256 balance) {\n return accounts[accountId].tokenPositions.vQuoteBalance;\n }\n\n function getAccountLiquidityPositionNum(uint256 accountId, address vToken) external view returns (uint8 num) {\n LiquidityPosition.Set storage liquidityPositionSet = accounts[accountId]\n .tokenPositions\n .positions[vToken.truncate()]\n .liquidityPositions;\n\n for (num = 0; num < liquidityPositionSet.active.length; num++) {\n if (liquidityPositionSet.active[num] == 0) break;\n }\n }\n\n function getAccountLiquidityPositionDetails(\n uint256 accountId,\n address vToken,\n uint8 num\n )\n external\n view\n returns (\n int24 tickLower,\n int24 tickUpper,\n IClearingHouseEnums.LimitOrderType limitOrderType,\n uint128 liquidity,\n int256 vTokenAmountIn,\n int256 sumALastX128,\n int256 sumBInsideLastX128,\n int256 sumFpInsideLastX128,\n uint256 sumFeeInsideLastX128\n )\n {\n LiquidityPosition.Set storage liquidityPositionSet = accounts[accountId]\n .tokenPositions\n .positions[vToken.truncate()]\n .liquidityPositions;\n LiquidityPosition.Info storage liquidityPosition = liquidityPositionSet.positions[\n liquidityPositionSet.active[num]\n ];\n\n return (\n liquidityPosition.tickLower,\n liquidityPosition.tickUpper,\n liquidityPosition.limitOrderType,\n liquidityPosition.liquidity,\n liquidityPosition.vTokenAmountIn,\n liquidityPosition.sumALastX128,\n liquidityPosition.sumBInsideLastX128,\n liquidityPosition.sumFpInsideLastX128,\n liquidityPosition.sumFeeInsideLastX128\n );\n }\n\n function getAccountValueAndRequiredMargin(uint256 accountId, bool isInitialMargin)\n external\n view\n returns (int256 accountMarketValue, int256 requiredMargin)\n {\n (accountMarketValue, requiredMargin) = accounts[accountId].getAccountValueAndRequiredMargin(\n isInitialMargin,\n protocol\n );\n }\n\n function getAccountProfit(uint256 accountId) external view returns (int256 profit) {\n return accounts[accountId].tokenPositions.getAccountMarketValue(protocol);\n }\n}\n" + }, + "contracts/test/Uint32L8ArrayTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Uint32L8ArrayLib } from '../libraries/Uint32L8Array.sol';\n\ncontract Uint32L8ArrayTest {\n using Uint32L8ArrayLib for uint32[8];\n\n uint32[8] array;\n\n // EXPOSING LIBRARY METHODS\n\n function include(uint32 element) external {\n array.include(element);\n }\n\n function exclude(uint32 element) external {\n array.exclude(element);\n }\n\n // DEBUG METHODS\n\n function getter(uint8 index) public view returns (uint32) {\n return array[index];\n }\n\n function getterAll() public view returns (uint32[8] memory) {\n return array;\n }\n\n function length() public view returns (uint8 len) {\n for (uint256 i = 0; i < 8; i++) {\n if (array[i] != 0) {\n len++;\n }\n if (array[i] == 0) {\n break;\n }\n }\n }\n\n function setter(uint8 index, uint32 element) public {\n array[index] = element;\n }\n\n function exists(uint32 element) public view returns (bool) {\n return array.exists(element);\n }\n\n function numberOfNonZeroElements() public view returns (uint256) {\n return array.numberOfNonZeroElements();\n }\n}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/libraries/TickBitmap.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {BitMath} from './BitMath.sol';\n\n/// @title Packed tick initialized state library\n/// @notice Stores a packed mapping of tick index to its initialized state\n/// @dev The mapping uses int16 for keys since ticks are represented as int24 and there are 256 (2^8) values per word.\nlibrary TickBitmap {\n /// @notice Computes the position in the mapping where the initialized bit for a tick lives\n /// @param tick The tick for which to compute the position\n /// @return wordPos The key in the mapping containing the word in which the bit is stored\n /// @return bitPos The bit position in the word where the flag is stored\n function position(int24 tick) internal pure returns (int16 wordPos, uint8 bitPos) {\n unchecked {\n wordPos = int16(tick >> 8);\n bitPos = uint8(int8(tick % 256));\n }\n }\n\n /// @notice Flips the initialized state for a given tick from false to true, or vice versa\n /// @param self The mapping in which to flip the tick\n /// @param tick The tick to flip\n /// @param tickSpacing The spacing between usable ticks\n function flipTick(\n mapping(int16 => uint256) storage self,\n int24 tick,\n int24 tickSpacing\n ) internal {\n unchecked {\n require(tick % tickSpacing == 0); // ensure that the tick is spaced\n (int16 wordPos, uint8 bitPos) = position(tick / tickSpacing);\n uint256 mask = 1 << bitPos;\n self[wordPos] ^= mask;\n }\n }\n\n /// @notice Returns the next initialized tick contained in the same word (or adjacent word) as the tick that is either\n /// to the left (less than or equal to) or right (greater than) of the given tick\n /// @param self The mapping in which to compute the next initialized tick\n /// @param tick The starting tick\n /// @param tickSpacing The spacing between usable ticks\n /// @param lte Whether to search for the next initialized tick to the left (less than or equal to the starting tick)\n /// @return next The next initialized or uninitialized tick up to 256 ticks away from the current tick\n /// @return initialized Whether the next tick is initialized, as the function only searches within up to 256 ticks\n function nextInitializedTickWithinOneWord(\n mapping(int16 => uint256) storage self,\n int24 tick,\n int24 tickSpacing,\n bool lte\n ) internal view returns (int24 next, bool initialized) {\n unchecked {\n int24 compressed = tick / tickSpacing;\n if (tick < 0 && tick % tickSpacing != 0) compressed--; // round towards negative infinity\n\n if (lte) {\n (int16 wordPos, uint8 bitPos) = position(compressed);\n // all the 1s at or to the right of the current bitPos\n uint256 mask = (1 << bitPos) - 1 + (1 << bitPos);\n uint256 masked = self[wordPos] & mask;\n\n // if there are no initialized ticks to the right of or at the current tick, return rightmost in the word\n initialized = masked != 0;\n // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick\n next = initialized\n ? (compressed - int24(uint24(bitPos - BitMath.mostSignificantBit(masked)))) * tickSpacing\n : (compressed - int24(uint24(bitPos))) * tickSpacing;\n } else {\n // start from the word of the next tick, since the current tick state doesn't matter\n (int16 wordPos, uint8 bitPos) = position(compressed + 1);\n // all the 1s at or to the left of the bitPos\n uint256 mask = ~((1 << bitPos) - 1);\n uint256 masked = self[wordPos] & mask;\n\n // if there are no initialized ticks to the left of the current tick, return leftmost in the word\n initialized = masked != 0;\n // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick\n next = initialized\n ? (compressed + 1 + int24(uint24(BitMath.leastSignificantBit(masked) - bitPos))) * tickSpacing\n : (compressed + 1 + int24(uint24(type(uint8).max - bitPos))) * tickSpacing;\n }\n }\n }\n}\n" + }, + "@uniswap/v3-core-0.8-support/contracts/libraries/Simulate.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {SwapMath} from './SwapMath.sol';\nimport {SafeCast} from './SafeCast.sol';\nimport {TickMath} from './TickMath.sol';\nimport {TickBitmap} from './TickBitmap.sol';\nimport {BitMath} from './BitMath.sol';\n\nimport {IUniswapV3Pool} from '../interfaces/IUniswapV3Pool.sol';\n\n/// @title Library for simulating swaps.\n/// @notice By fully replicating the swap logic, we can make a static call to get a quote.\nlibrary Simulate {\n using SafeCast for uint256;\n\n struct Cache {\n // price at the beginning of the swap\n uint160 sqrtPriceX96Start;\n // tick at the beginning of the swap\n int24 tickStart;\n // liquidity at the beginning of the swap\n uint128 liquidityStart;\n // the lp fee of the pool\n uint24 fee;\n // the tick spacing of the pool\n int24 tickSpacing;\n }\n\n struct State {\n // the amount remaining to be swapped in/out of the input/output asset\n int256 amountSpecifiedRemaining;\n // the amount already swapped out/in of the output/input asset\n int256 amountCalculated;\n // current sqrt(price)\n uint160 sqrtPriceX96;\n // the tick associated with the current price\n int24 tick;\n // the current liquidity in range\n uint128 liquidity;\n }\n\n // copied from UniswapV3Pool to avoid pragma issues associated with importing it\n struct StepComputations {\n // the price at the beginning of the step\n uint160 sqrtPriceStartX96;\n // the next tick to swap to from the current tick in the swap direction\n int24 tickNext;\n // whether tickNext is initialized or not\n bool initialized;\n // sqrt(price) for the next tick (1/0)\n uint160 sqrtPriceNextX96;\n // how much is being swapped in in this step\n uint256 amountIn;\n // how much is being swapped out\n uint256 amountOut;\n // how much fee is being paid in\n uint256 feeAmount;\n }\n\n function simulateSwap(\n IUniswapV3Pool pool,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96\n ) internal view returns (int256 amount0, int256 amount1) {\n require(amountSpecified != 0, 'AS');\n\n (uint160 sqrtPriceX96, int24 tick, , , , , ) = pool.slot0();\n\n require(\n zeroForOne\n ? sqrtPriceLimitX96 < sqrtPriceX96 && sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO\n : sqrtPriceLimitX96 > sqrtPriceX96 && sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO,\n 'SPL'\n );\n\n Cache memory cache = Cache({\n sqrtPriceX96Start: sqrtPriceX96,\n tickStart: tick,\n liquidityStart: pool.liquidity(),\n fee: pool.fee(),\n tickSpacing: pool.tickSpacing()\n });\n\n bool exactInput = amountSpecified > 0;\n\n State memory state = State({\n amountSpecifiedRemaining: amountSpecified,\n amountCalculated: 0,\n sqrtPriceX96: cache.sqrtPriceX96Start,\n tick: cache.tickStart,\n liquidity: cache.liquidityStart\n });\n\n while (state.amountSpecifiedRemaining != 0 && state.sqrtPriceX96 != sqrtPriceLimitX96) {\n StepComputations memory step;\n\n step.sqrtPriceStartX96 = state.sqrtPriceX96;\n\n (step.tickNext, step.initialized) = nextInitializedTickWithinOneWord(\n pool.tickBitmap,\n state.tick,\n cache.tickSpacing,\n zeroForOne\n );\n\n if (step.tickNext < TickMath.MIN_TICK) {\n step.tickNext = TickMath.MIN_TICK;\n } else if (step.tickNext > TickMath.MAX_TICK) {\n step.tickNext = TickMath.MAX_TICK;\n }\n\n step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext);\n\n (state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep(\n state.sqrtPriceX96,\n (zeroForOne ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 : step.sqrtPriceNextX96 > sqrtPriceLimitX96)\n ? sqrtPriceLimitX96\n : step.sqrtPriceNextX96,\n state.liquidity,\n state.amountSpecifiedRemaining,\n cache.fee\n );\n\n if (exactInput) {\n unchecked {\n state.amountSpecifiedRemaining -= (step.amountIn + step.feeAmount).toInt256();\n }\n state.amountCalculated -= step.amountOut.toInt256();\n } else {\n unchecked {\n state.amountSpecifiedRemaining += step.amountOut.toInt256();\n }\n state.amountCalculated += (step.amountIn + step.feeAmount).toInt256();\n }\n\n if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {\n if (step.initialized) {\n (, int128 liquidityNet, , , , , , ) = pool.ticks(step.tickNext);\n unchecked {\n if (zeroForOne) liquidityNet = -liquidityNet;\n }\n\n state.liquidity = liquidityNet < 0\n ? state.liquidity - uint128(-liquidityNet)\n : state.liquidity + uint128(liquidityNet);\n }\n\n unchecked {\n state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;\n }\n } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) {\n // recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved\n state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96);\n }\n }\n\n (amount0, amount1) = zeroForOne == exactInput\n ? (amountSpecified - state.amountSpecifiedRemaining, state.amountCalculated)\n : (state.amountCalculated, amountSpecified - state.amountSpecifiedRemaining);\n }\n\n // This function replicates TickBitmap, but accepts a function pointer argument.\n // It's private because it's messy, and shouldn't be re-used.\n function nextInitializedTickWithinOneWord(\n function(int16) external view returns (uint256) self,\n int24 tick,\n int24 tickSpacing,\n bool lte\n ) private view returns (int24 next, bool initialized) {\n unchecked {\n int24 compressed = tick / tickSpacing;\n if (tick < 0 && tick % tickSpacing != 0) compressed--; // round towards negative infinity\n\n if (lte) {\n (int16 wordPos, uint8 bitPos) = TickBitmap.position(compressed);\n // all the 1s at or to the right of the current bitPos\n uint256 mask = (1 << bitPos) - 1 + (1 << bitPos);\n uint256 masked = self(wordPos) & mask;\n\n // if there are no initialized ticks to the right of or at the current tick, return rightmost in the word\n initialized = masked != 0;\n // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick\n next = initialized\n ? (compressed - int24(uint24(bitPos - BitMath.mostSignificantBit(masked)))) * tickSpacing\n : (compressed - int24(uint24(bitPos))) * tickSpacing;\n } else {\n // start from the word of the next tick, since the current tick state doesn't matter\n (int16 wordPos, uint8 bitPos) = TickBitmap.position(compressed + 1);\n // all the 1s at or to the left of the bitPos\n uint256 mask = ~((1 << bitPos) - 1);\n uint256 masked = self(wordPos) & mask;\n\n // if there are no initialized ticks to the left of the current tick, return leftmost in the word\n initialized = masked != 0;\n // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick\n next = initialized\n ? (compressed + 1 + int24(uint24(BitMath.leastSignificantBit(masked) - bitPos))) * tickSpacing\n : (compressed + 1 + int24(uint24(type(uint8).max - bitPos))) * tickSpacing;\n }\n }\n }\n}\n" + }, + "contracts/lens/SwapSimulator.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.4;\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\nimport { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';\nimport { Simulate as SimulateUniswap } from '@uniswap/v3-core-0.8-support/contracts/libraries/Simulate.sol';\n\nimport { IClearingHouse } from '../interfaces/IClearingHouse.sol';\nimport { IClearingHouseStructures } from '../interfaces/clearinghouse/IClearingHouseStructures.sol';\nimport { IVPoolWrapper } from '../interfaces/IVPoolWrapper.sol';\nimport { IVToken } from '../interfaces/IVToken.sol';\n\nimport { ClearingHouseExtsload } from '../extsloads/ClearingHouseExtsload.sol';\nimport { SimulateSwap } from '../libraries/SimulateSwap.sol';\nimport { SwapMath } from '../libraries/SwapMath.sol';\nimport { UniswapV3PoolHelper } from '../libraries/UniswapV3PoolHelper.sol';\n\ncontract SwapSimulator {\n using ClearingHouseExtsload for IClearingHouse;\n using SimulateSwap for IUniswapV3Pool;\n\n struct SwapStepAndState {\n SimulateSwap.Step step;\n SimulateSwap.State state;\n }\n\n SwapStepAndState[] _steps;\n\n /// @notice Simulate Swap with detailed tick cross info\n /// @dev These parameters are similar to ClearingHouse's swapToken function\n /// @param clearingHouse The ClearingHouse address\n /// @param poolId The poolId of the pool to be simulated on\n /// @param amount The amount of token to be swapped, positive for long, negative for short\n /// @param sqrtPriceLimitX96 The slippage limit of the swap, use zero for unbounded slippage\n /// @param isNotional Whether the amount is in vQuote/dollar terms, use false for vToken\n function simulateSwap(\n IClearingHouse clearingHouse,\n uint32 poolId,\n int256 amount,\n uint160 sqrtPriceLimitX96,\n bool isNotional\n )\n public\n returns (\n IVPoolWrapper.SwapResult memory swapResult,\n SimulateSwap.Cache memory cache,\n SwapStepAndState[] memory steps\n )\n {\n IClearingHouseStructures.Pool memory poolInfo = clearingHouse.getPoolInfo(poolId);\n\n return\n simulateSwapOnVPool(\n poolInfo.vPool,\n poolInfo.vPoolWrapper.liquidityFeePips(),\n poolInfo.vPoolWrapper.protocolFeePips(),\n amount < 0,\n isNotional ? amount : -amount,\n sqrtPriceLimitX96\n );\n }\n\n /// @notice Simulate Swap with detailed tick cross info\n /// @dev These parameters are similar to IUniswapV3Pool's swap function\n /// @param vPool The vPool address\n /// @param liquidityFeePips The liquidity fee pips, available from poolInfo in clearingHouse\n /// @param protocolFeePips The protocol fee pips, available from poolInfo in clearingHouse\n /// @param swapVTokenForVQuote Whether vToken is being sold or shorted\n /// @param amountSpecified Amount to be swapped, positive for exactIn and negative for exactOut\n /// @param sqrtPriceLimitX96 The slippage limit of the swap, use zero for unbounded slippage\n function simulateSwapOnVPool(\n IUniswapV3Pool vPool,\n uint24 liquidityFeePips,\n uint24 protocolFeePips,\n bool swapVTokenForVQuote, // zeroForOne\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96\n )\n public\n returns (\n IVPoolWrapper.SwapResult memory swapResult,\n SimulateSwap.Cache memory cache,\n SwapStepAndState[] memory steps\n )\n {\n delete _steps;\n\n if (sqrtPriceLimitX96 == 0) {\n sqrtPriceLimitX96 = swapVTokenForVQuote ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1;\n }\n\n swapResult.amountSpecified = amountSpecified;\n uint24 uniswapFeePips = vPool.fee();\n\n SwapMath.beforeSwap(\n amountSpecified >= 0, // exactIn\n swapVTokenForVQuote,\n uniswapFeePips,\n liquidityFeePips,\n protocolFeePips,\n swapResult\n );\n\n // simulate swap and record tick crosses\n SimulateSwap.State memory state;\n (swapResult.vTokenIn, swapResult.vQuoteIn, state, cache) = vPool.simulateSwap(\n swapVTokenForVQuote,\n swapResult.amountSpecified,\n sqrtPriceLimitX96,\n _onSwapStep\n );\n\n SwapMath.afterSwap(\n amountSpecified >= 0, // exactIn\n swapVTokenForVQuote,\n uniswapFeePips,\n liquidityFeePips,\n protocolFeePips,\n swapResult\n );\n\n swapResult.sqrtPriceX96Start = cache.sqrtPriceX96Start;\n swapResult.sqrtPriceX96End = state.sqrtPriceX96;\n\n steps = _steps;\n }\n\n /// @notice Simulate Swap in a cheap way, by ignoring any tick cross details\n /// @dev These parameters are similar to ClearingHouse's swapToken function\n /// @param clearingHouse The ClearingHouse address\n /// @param poolId The poolId of the pool to be simulated on\n /// @param amount The amount of token to be swapped, positive for long, negative for short\n /// @param sqrtPriceLimitX96 The slippage limit of the swap, use zero for unbounded slippage\n /// @param isNotional Whether the amount is in vQuote/dollar terms, use false for vToken\n function simulateSwapView(\n IClearingHouse clearingHouse,\n uint32 poolId,\n int256 amount,\n uint160 sqrtPriceLimitX96,\n bool isNotional\n ) public view returns (IVPoolWrapper.SwapResult memory swapResult) {\n IClearingHouseStructures.Pool memory poolInfo = clearingHouse.getPoolInfo(poolId);\n\n swapResult = simulateSwapOnVPoolView(\n poolInfo.vPool,\n poolInfo.vPoolWrapper.liquidityFeePips(),\n poolInfo.vPoolWrapper.protocolFeePips(),\n amount < 0,\n isNotional ? amount : -amount,\n sqrtPriceLimitX96\n );\n }\n\n /// @notice Simulate Swap in a cheap way, by ignoring any tick cross details\n /// @dev These parameters are similar to IUniswapV3Pool's swap function\n /// @param vPool The vPool address\n /// @param liquidityFeePips The liquidity fee pips, available from poolInfo in clearingHouse\n /// @param protocolFeePips The protocol fee pips, available from poolInfo in clearingHouse\n /// @param swapVTokenForVQuote Whether vToken is being sold or shorted\n /// @param amountSpecified Amount to be swapped, positive for exactIn and negative for exactOut\n /// @param sqrtPriceLimitX96 The slippage limit of the swap, use zero for unbounded slippage\n function simulateSwapOnVPoolView(\n IUniswapV3Pool vPool,\n uint24 liquidityFeePips,\n uint24 protocolFeePips,\n bool swapVTokenForVQuote, // zeroForOne\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96\n ) public view returns (IVPoolWrapper.SwapResult memory swapResult) {\n if (sqrtPriceLimitX96 == 0) {\n sqrtPriceLimitX96 = swapVTokenForVQuote ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1;\n }\n\n swapResult.amountSpecified = amountSpecified;\n bool exactIn = amountSpecified >= 0;\n uint24 uniswapFeePips = vPool.fee();\n\n SwapMath.beforeSwap(\n exactIn,\n swapVTokenForVQuote,\n uniswapFeePips,\n liquidityFeePips,\n protocolFeePips,\n swapResult\n );\n\n // simulate swap and ignore tick crosses\n (swapResult.vTokenIn, swapResult.vQuoteIn) = SimulateUniswap.simulateSwap(\n vPool,\n swapVTokenForVQuote,\n swapResult.amountSpecified,\n sqrtPriceLimitX96\n );\n\n SwapMath.afterSwap(exactIn, swapVTokenForVQuote, uniswapFeePips, liquidityFeePips, protocolFeePips, swapResult);\n }\n\n function _onSwapStep(\n bool,\n SimulateSwap.Cache memory,\n SimulateSwap.State memory state,\n SimulateSwap.Step memory step\n ) internal {\n // for reading\n _steps.push(SwapStepAndState({ state: state, step: step }));\n }\n}\n" + }, + "contracts/oracles/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.8.4;\n\nimport { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\nimport { AggregatorV3Interface } from '@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol';\nimport { FlagsInterface } from '@chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol';\n\nimport { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';\n\nimport { AddressHelper } from '../libraries/AddressHelper.sol';\nimport { PriceMath } from '../libraries/PriceMath.sol';\n\nimport { IOracle } from '../interfaces/IOracle.sol';\n\ncontract ChainlinkOracle is IOracle {\n using AddressHelper for address;\n using FullMath for uint256;\n using SafeCast for uint256;\n using PriceMath for uint256;\n\n AggregatorV3Interface public aggregator;\n FlagsInterface public chainlinkFlags;\n\n uint8 immutable vTokenDecimals;\n uint8 immutable vQuoteDecimals;\n address private constant FLAG_ARBITRUM_SEQ_OFFLINE =\n address(bytes20(bytes32(uint256(keccak256('chainlink.flags.arbitrum-seq-offline')) - 1)));\n\n error NotEnoughHistory();\n error SequencerOffline();\n error IllegalAggregatorAddress(address aggregator);\n\n constructor(\n address _aggregator,\n address _flags,\n uint8 _vTokenDecimals,\n uint8 _vQuoteDecimals\n ) {\n if (_aggregator.isZero()) revert IllegalAggregatorAddress(address(0));\n aggregator = AggregatorV3Interface(_aggregator);\n chainlinkFlags = FlagsInterface(_flags);\n vTokenDecimals = _vTokenDecimals;\n vQuoteDecimals = _vQuoteDecimals;\n }\n\n function getTwapPriceX128(uint32 twapDuration) public view returns (uint256 priceX128) {\n priceX128 = getPrice(twapDuration);\n priceX128 = priceX128.mulDiv(\n FixedPoint128.Q128 * 10**(vQuoteDecimals),\n 10**(vTokenDecimals + aggregator.decimals())\n );\n }\n\n function getPrice(uint256 twapDuration) internal view returns (uint256) {\n FlagsInterface _chainlinkFlags = chainlinkFlags;\n if (address(_chainlinkFlags) != address(0)) {\n bool isRaised = _chainlinkFlags.getFlag(FLAG_ARBITRUM_SEQ_OFFLINE);\n if (isRaised) {\n revert SequencerOffline();\n }\n }\n (uint80 round, uint256 latestPrice, uint256 latestTS) = _getLatestRoundData();\n uint256 endTS = block.timestamp;\n uint256 thresholdTS = endTS - twapDuration;\n\n //If twap duration = 0 or less data available just return latestPrice\n if (twapDuration == 0 || round == 0 || latestTS <= thresholdTS) {\n return latestPrice;\n }\n\n uint256 totalTime = endTS - latestTS;\n uint256 twap = latestPrice * totalTime;\n uint256 periodLength;\n uint256 startTS;\n uint256 periodPrice;\n\n endTS = latestTS;\n\n //Aggregate prices for all the eligible rounds before thresholdTS i.e. adds price*periodLength to twap\n //For the last eligible round goes till thresholdTS only\n while (true) {\n //If 0 round is reached before reaching thresholdTS then just consider the available data\n if (round == 0) {\n return totalTime == 0 ? latestPrice : twap / totalTime;\n }\n\n round = round - 1;\n (, periodPrice, startTS) = _getRoundData(round);\n if (periodPrice == 0) break;\n //If the starting time of a period is lesser than threshold timestamp (now-twapDuration) then period is thresholdTS -> endTS\n if (startTS <= thresholdTS) {\n periodLength = (endTS - thresholdTS);\n twap += periodPrice * periodLength;\n totalTime += periodLength;\n break;\n }\n\n // In normal case where thresholdTS < startTS. The whole period is considered i.e. startTS -> endTS\n periodLength = (endTS - startTS);\n twap += (periodPrice * periodLength);\n totalTime += periodLength;\n\n //endTS of previous period = startTS of current period\n endTS = startTS;\n }\n\n //Divide the accumulated value by the whole duration\n return twap == 0 ? latestPrice : twap / totalTime;\n }\n\n function _getLatestRoundData()\n private\n view\n returns (\n uint80,\n uint256 finalPrice,\n uint256\n )\n {\n (uint80 round, int256 latestPrice, , uint256 latestTS, ) = aggregator.latestRoundData();\n\n if (latestPrice < 0 && round <= 0) revert NotEnoughHistory();\n\n if (latestPrice < 0) {\n (round, finalPrice, latestTS) = _getRoundData(round - 1);\n } else {\n finalPrice = uint256(latestPrice);\n }\n return (round, finalPrice, latestTS);\n }\n\n function _getRoundData(uint80 _round)\n private\n view\n returns (\n uint80,\n uint256,\n uint256\n )\n {\n (uint80 round, int256 latestPrice, , uint256 latestTS, ) = _getRoundDataWithCheck(_round);\n while (latestPrice < 0 && round > 0) {\n round = round - 1;\n (, latestPrice, , latestTS, ) = aggregator.getRoundData(round);\n }\n if (latestPrice < 0 && round <= 0) revert NotEnoughHistory();\n return (round, uint256(latestPrice), latestTS);\n }\n\n function _getRoundDataWithCheck(uint80 _round)\n private\n view\n returns (\n uint80,\n int256,\n uint256,\n uint256,\n uint80\n )\n {\n try aggregator.getRoundData(_round) returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n ) {\n return (roundId, answer, startedAt, updatedAt, answeredInRound);\n } catch {\n return (0, 0, 0, 0, 0);\n }\n }\n}\n" + }, + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "@chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface FlagsInterface {\n function getFlag(address) external view returns (bool);\n\n function getFlags(address[] calldata) external view returns (bool[] memory);\n\n function raiseFlag(address) external;\n\n function raiseFlags(address[] calldata) external;\n\n function lowerFlags(address[] calldata) external;\n\n function setRaisingAccessController(address) external;\n}\n" + }, + "contracts/test/SignedMathTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { SignedMath } from '../libraries/SignedMath.sol';\n\n/// @title Signed math functions\ncontract SignedMathTest {\n function abs(int256 value) external pure returns (int256) {\n return SignedMath.abs(value);\n }\n\n function absUint(int256 value) external pure returns (uint256) {\n return SignedMath.absUint(value);\n }\n\n function sign(int256 value) external pure returns (int256) {\n return SignedMath.sign(value);\n }\n\n /// @notice Converts a signed integer into an unsigned integer and inverts positive bool if negative\n function extractSign(int256 a, bool positive) external pure returns (uint256 _a, bool) {\n return SignedMath.extractSign(a, positive);\n }\n\n function extractSign(int256 a) external pure returns (uint256 _a, bool) {\n return SignedMath.extractSign(a);\n }\n}\n" + }, + "contracts/test/SignedFullMathTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';\nimport { SignedFullMath } from '../libraries/SignedFullMath.sol';\n\ncontract SignedFullMathTest {\n function mulDiv(\n uint256 a,\n uint256 b,\n uint256 denominator\n ) public pure returns (uint256 result) {\n return FullMath.mulDiv(a, b, denominator);\n }\n\n function mulDiv(\n int256 a,\n uint256 b,\n uint256 denominator\n ) public pure returns (int256 result) {\n return SignedFullMath.mulDiv(a, b, denominator);\n }\n\n function mulDiv(\n int256 a,\n int256 b,\n int256 denominator\n ) public pure returns (int256 result) {\n return SignedFullMath.mulDiv(a, b, denominator);\n }\n\n function mulDivRoundingUp(\n uint256 a,\n uint256 b,\n uint256 denominator\n ) public pure returns (uint256 result) {\n return FullMath.mulDivRoundingUp(a, b, denominator);\n }\n\n function mulDivRoundingDown(\n int256 a,\n uint256 b,\n uint256 denominator\n ) public pure returns (int256 result) {\n return SignedFullMath.mulDivRoundingDown(a, b, denominator);\n }\n\n function mulDivRoundingDown(\n int256 a,\n int256 b,\n int256 denominator\n ) public pure returns (int256 result) {\n return SignedFullMath.mulDivRoundingDown(a, b, denominator);\n }\n}\n" + }, + "contracts/test/FundingPaymentTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';\n\nimport { FundingPayment } from '../libraries/FundingPayment.sol';\nimport { SignedFullMath } from '../libraries/SignedFullMath.sol';\n\ncontract FundingPaymentTest {\n using SignedFullMath for int256;\n\n using FundingPayment for FundingPayment.Info;\n\n FundingPayment.Info public fpGlobal;\n\n function getFundingRate(uint256 realPriceX128, uint256 virtualPriceX128)\n internal\n pure\n returns (int256 fundingRateX128)\n {\n return FundingPayment.getFundingRate(realPriceX128, virtualPriceX128);\n }\n\n function update(\n int256 vTokenAmount,\n uint256 liquidity,\n uint48 blockTimestamp,\n uint256 realPriceX128,\n uint256 virtualPriceX128\n ) public {\n return\n fpGlobal.update(\n vTokenAmount,\n liquidity,\n blockTimestamp,\n FundingPayment.getFundingRate(realPriceX128, virtualPriceX128),\n virtualPriceX128\n );\n }\n\n function nextAX128(\n uint48 timestampLast,\n uint48 blockTimestamp,\n uint256 realPriceX128,\n uint256 virtualPriceX128\n ) public pure returns (int256) {\n return\n FundingPayment.nextAX128(\n timestampLast,\n blockTimestamp,\n FundingPayment.getFundingRate(realPriceX128, virtualPriceX128),\n virtualPriceX128\n );\n }\n\n function extrapolatedSumAX128(\n int256 sumA,\n uint48 timestampLast,\n uint48 blockTimestamp,\n uint256 realPriceX128,\n uint256 virtualPriceX128\n ) public pure returns (int256) {\n return\n FundingPayment.extrapolatedSumAX128(\n sumA,\n timestampLast,\n blockTimestamp,\n FundingPayment.getFundingRate(realPriceX128, virtualPriceX128),\n virtualPriceX128\n );\n }\n\n function extrapolatedSumFpX128(\n int256 sumAX128,\n int256 sumBX128,\n int256 sumFpX128,\n int256 sumALatestX128\n ) public pure returns (int256) {\n return FundingPayment.extrapolatedSumFpX128(sumAX128, sumBX128, sumFpX128, sumALatestX128);\n }\n\n function billLp(\n int256 sumAX128,\n int256 sumFpInsideX128,\n int256 sumALastX128,\n int256 sumBInsideLastX128,\n int256 sumFpInsideLastX128,\n uint256 liquidity\n ) internal pure returns (int256) {\n return\n FundingPayment.bill(\n sumAX128,\n sumFpInsideX128,\n sumALastX128,\n sumBInsideLastX128,\n sumFpInsideLastX128,\n liquidity\n );\n }\n\n function billTrader(\n int256 sumAX128,\n int256 sumALastX128,\n int256 netTraderPosition\n ) internal pure returns (int256) {\n return FundingPayment.bill(sumAX128, sumALastX128, netTraderPosition);\n }\n}\n" + }, + "contracts/test/mocks/MockAggregatorV2.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.12;\n\nimport { AggregatorV3Interface } from '@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol';\n\ncontract MockAggregatorV3 is AggregatorV3Interface {\n function decimals() external view returns (uint8) {}\n\n function description() external view returns (string memory) {}\n\n function version() external view returns (uint256) {}\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n )\n {}\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n )\n {}\n}\n" + }, + "contracts/lens/ClearingHouseLens.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\n\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport { IUniswapV3Pool } from '@uniswap/v3-core-0.8-support/contracts/interfaces/IUniswapV3Pool.sol';\n\nimport { IClearingHouse } from '../interfaces/IClearingHouse.sol';\nimport { IVQuote } from '../interfaces/IVQuote.sol';\n\nimport { ClearingHouseExtsload } from '../extsloads/ClearingHouseExtsload.sol';\n\ncontract ClearingHouseLens {\n using ClearingHouseExtsload for IClearingHouse;\n\n IClearingHouse public immutable clearingHouse;\n\n constructor(IClearingHouse _clearingHouse) {\n clearingHouse = _clearingHouse;\n }\n\n function getProtocolInfo()\n external\n view\n returns (\n IERC20 settlementToken,\n IVQuote vQuote,\n IClearingHouse.LiquidationParams memory liquidationParams,\n uint256 minRequiredMargin,\n uint256 removeLimitOrderFee,\n uint256 minimumOrderNotional\n )\n {\n return clearingHouse.getProtocolInfo();\n }\n\n function getPoolInfo(uint32 poolId) external view returns (IClearingHouse.Pool memory pool) {\n return clearingHouse.getPoolInfo(poolId);\n }\n\n function getVPool(uint32 poolId) external view returns (IUniswapV3Pool vPool) {\n return clearingHouse.getVPool(poolId);\n }\n\n function getPoolSettings(uint32 poolId) external view returns (IClearingHouse.PoolSettings memory settings) {\n return clearingHouse.getPoolSettings(poolId);\n }\n\n function getTwapDuration(uint32 poolId) external view returns (uint32 twapDuration) {\n return clearingHouse.getTwapDuration(poolId);\n }\n\n function getVPoolAndTwapDuration(uint32 poolId) external view returns (IUniswapV3Pool vPool, uint32 twapDuration) {\n return clearingHouse.getVPoolAndTwapDuration(poolId);\n }\n\n function isPoolIdAvailable(uint32 poolId) external view returns (bool) {\n return clearingHouse.isPoolIdAvailable(poolId);\n }\n\n function getCollateralInfo(uint32 collateralId) external view returns (IClearingHouse.Collateral memory) {\n return clearingHouse.getCollateralInfo(collateralId);\n }\n\n function getAccountInfo(uint256 accountId)\n external\n view\n returns (\n address owner,\n int256 vQuoteBalance,\n uint32[] memory activeCollateralIds,\n uint32[] memory activePoolIds\n )\n {\n return clearingHouse.getAccountInfo(accountId);\n }\n\n function getAccountCollateralInfo(uint256 accountId, uint32 collateralId)\n external\n view\n returns (IERC20 collateral, uint256 balance)\n {\n return clearingHouse.getAccountCollateralInfo(accountId, collateralId);\n }\n\n function getAccountCollateralBalance(uint256 accountId, uint32 collateralId)\n external\n view\n returns (uint256 balance)\n {\n return clearingHouse.getAccountCollateralBalance(accountId, collateralId);\n }\n\n function getAccountTokenPositionInfo(uint256 accountId, uint32 poolId)\n external\n view\n returns (\n int256 balance,\n int256 netTraderPosition,\n int256 sumALastX128\n )\n {\n return clearingHouse.getAccountTokenPositionInfo(accountId, poolId);\n }\n\n function getAccountPositionInfo(uint256 accountId, uint32 poolId)\n external\n view\n returns (\n int256 balance,\n int256 netTraderPosition,\n int256 sumALastX128,\n IClearingHouse.TickRange[] memory activeTickRanges\n )\n {\n return clearingHouse.getAccountPositionInfo(accountId, poolId);\n }\n\n function getAccountLiquidityPositionList(uint256 accountId, uint32 poolId)\n external\n view\n returns (IClearingHouse.TickRange[] memory activeTickRanges)\n {\n return clearingHouse.getAccountLiquidityPositionList(accountId, poolId);\n }\n\n function getAccountLiquidityPositionInfo(\n uint256 accountId,\n uint32 poolId,\n int24 tickLower,\n int24 tickUpper\n )\n external\n view\n returns (\n uint8 limitOrderType,\n uint128 liquidity,\n int256 vTokenAmountIn,\n int256 sumALastX128,\n int256 sumBInsideLastX128,\n int256 sumFpInsideLastX128,\n uint256 sumFeeInsideLastX128\n )\n {\n return clearingHouse.getAccountLiquidityPositionInfo(accountId, poolId, tickLower, tickUpper);\n }\n}\n" + }, + "contracts/test/BatchedLoopTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { BatchedLoop } from '../libraries/BatchedLoop.sol';\n\ncontract BatchedLoopTest {\n using BatchedLoop for BatchedLoop.Info;\n\n BatchedLoop.Info public loop;\n\n uint256[] input;\n uint256[] output;\n\n function setInput(uint256[] memory _input) public {\n input = _input;\n }\n\n function getOutput() public view returns (uint256[] memory) {\n return output;\n }\n\n function isInProgress() public view returns (bool) {\n return loop.isInProgress();\n }\n\n function iterate(uint256 iterations, bool expectTrue) public {\n require(\n loop.iterate({\n startAt: 0,\n endBefore: input.length,\n batchSize: iterations,\n execute: forEachArrayElement\n }) == expectTrue\n );\n }\n\n function forEachArrayElement(uint256 i) private {\n output.push(input[i]);\n }\n}\n\ncontract BatchedLoopTest2 {\n using BatchedLoop for BatchedLoop.Info;\n\n BatchedLoop.Info public iteration;\n\n uint256[] output;\n\n function getOutput() public view returns (uint256[] memory) {\n return output;\n }\n\n function isInProgress() public view returns (bool) {\n return iteration.isInProgress();\n }\n\n function iterate(\n uint256 startAt,\n uint256 endBefore,\n uint256 batchSize,\n bool expectTrue\n ) public {\n require(iteration.iterate(startAt, endBefore, batchSize, squarePlusOne) == expectTrue);\n }\n\n function squarePlusOne(uint256 i) private {\n output.push(i * i + 1);\n }\n}\n" + }, + "contracts/test/GoodAddressDeployerTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { GoodAddressDeployer } from '../libraries/GoodAddressDeployer.sol';\n\ncontract GoodAddressDeployerTest {\n receive() external payable {}\n\n event Address(address val);\n\n function deploy(uint256 amount, bytes memory bytecode) external returns (address computed) {\n computed = GoodAddressDeployer.deploy(amount, bytecode, _isAddressGood);\n emit Address(computed);\n }\n\n // to be overriden using smock\n function isAddressGood(address) external pure returns (bool) {\n return false;\n }\n\n function _isAddressGood(address input) internal view returns (bool) {\n return this.isAddressGood(input);\n }\n}\n" + }, + "contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol';\n" + }, + "contracts/test/BisectionTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Bisection } from '../libraries/Bisection.sol';\n\ncontract BisectionTest {\n function increasingFunction(uint160 val) public pure returns (uint256) {\n return (val * 3);\n }\n\n function findSolution(\n uint256 y_target,\n uint160 x_lower,\n uint160 x_upper\n ) external pure returns (uint160) {\n return Bisection.findSolution(increasingFunction, y_target, x_lower, x_upper);\n }\n}\n" + }, + "contracts/test/LiquidityPositionSetTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { LiquidityPositionSet, LiquidityPosition } from '../libraries/LiquidityPositionSet.sol';\nimport { VPoolWrapperMock } from './mocks/VPoolWrapperMock.sol';\n\ncontract LiquidityPositionSetTest {\n using LiquidityPositionSet for LiquidityPosition.Set;\n using LiquidityPosition for LiquidityPosition.Info;\n\n LiquidityPosition.Set liquidityPositions;\n VPoolWrapperMock public wrapper;\n\n constructor() {\n wrapper = new VPoolWrapperMock();\n }\n\n function isPositionActive(int24 tickLower, int24 tickUpper) public view returns (bool) {\n return liquidityPositions.isPositionActive(tickLower, tickUpper);\n }\n\n function createEmptyPosition(int24 tickLower, int24 tickUpper)\n external\n returns (LiquidityPosition.Info memory info)\n {\n info = liquidityPositions.activate(tickLower, tickUpper);\n }\n}\n" + }, + "contracts/test/Uint48L5ArrayTest.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.9;\n\nimport { Uint48L5ArrayLib } from '../libraries/Uint48L5Array.sol';\n\ncontract Uint48L5ArrayTest {\n using Uint48L5ArrayLib for uint48[5];\n\n uint48[5] array;\n\n // EXPOSING LIBRARY METHODS\n\n function include(uint48 element) external {\n array.include(element);\n }\n\n function exclude(uint48 element) external {\n array.exclude(element);\n }\n\n // DEBUG METHODS\n\n function getter(uint8 index) public view returns (uint48) {\n return array[index];\n }\n\n function getterAll() public view returns (uint48[5] memory) {\n return array;\n }\n\n function length() public view returns (uint8 len) {\n for (uint256 i = 0; i < 5; i++) {\n if (array[i] != 0) {\n len++;\n }\n if (array[i] == 0) {\n break;\n }\n }\n }\n\n function setter(uint8 index, uint48 element) public {\n array[index] = element;\n }\n\n function exists(uint48 element) public view returns (bool) {\n return array.exists(element);\n }\n\n function numberOfNonZeroElements() public view returns (uint256) {\n return array.numberOfNonZeroElements();\n }\n}\n" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true, + "runs": 2000 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file